﻿Перем ТаблицаКлючевыхСлов;
Перем ЭтоУФ Экспорт;
Перем СоответствиеТаблицПереводов;
Перем ТекущийЯзыкФичаФайла;
Перем ПредставлениеВертЧертыВТабДок;

Процедура СделатьСообщение(Знач Сообщение) Экспорт
	Сообщить(Строка(ТекущаяДата()) + " " + Сообщение);
КонецПроцедуры

Процедура Отладка(Знач Сообщение) Экспорт
	Если DebugLog Тогда
		СделатьСообщение(Сообщение);
	КонецЕсли; 
КонецПроцедуры

Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",", Знач ПропускатьПустыеСтроки = Неопределено) Экспорт
	
	Результат = Новый Массив;
	
	// для обеспечения обратной совместимости
	Если ПропускатьПустыеСтроки = Неопределено Тогда
		ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
		Если ПустаяСтрока(Строка) Тогда 
			Если Разделитель = " " Тогда
				Результат.Добавить("");
			КонецЕсли;
			Возврат Результат;
		КонецЕсли;
	КонецЕсли;
	//
	
	Позиция = Найти(Строка, Разделитель);
	Пока Позиция > 0 Цикл
		Подстрока = Лев(Строка, Позиция - 1);
		Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
			Результат.Добавить(Подстрока);
		КонецЕсли;
		Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
		Позиция = Найти(Строка, Разделитель);
	КонецЦикла;
	
	Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
		Результат.Добавить(Строка);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции 

Функция ПолучитьКлючевоеСлово(Стр, ВтораяЧастьСтрокиПозиция=1)
	ТаблицаКлючевыхСлов = СоответствиеТаблицПереводов.Получить(ТекущийЯзыкФичаФайла);
	
	Для каждого СтрТаблицаКлючевыхСлов Из ТаблицаКлючевыхСлов Цикл
		Позиция = Найти(Стр, СтрТаблицаКлючевыхСлов.Слово);
		Если Позиция = 1 Тогда
			ВтораяЧастьСтрокиПозиция = СтрДлина(СтрТаблицаКлючевыхСлов.Слово)+1;
			Возврат СтрТаблицаКлючевыхСлов.Тип;
		КонецЕсли;
	КонецЦикла;
	
	Возврат "";
КонецФункции

Функция ПодготовитьСтрокуПримераКРазбору(Стр)
	НовСтр = "";
	Длина = СтрДлина(Стр);
	ЭтоПараметр = Ложь;
	Для Ккк = 1 По Длина Цикл
		Символ = Сред(Стр,Ккк,1);
		Если Символ = "'" Тогда
			ЭтоПараметр = Не ЭтоПараметр;
		ИначеЕсли Символ = "|" Тогда
			Если ЭтоПараметр Тогда
				Символ = ПредставлениеВертЧертыВТабДок;
			КонецЕсли;	 
		КонецЕсли;	 
		
		НовСтр = НовСтр + Символ;
	КонецЦикла; 
	
	Возврат НовСтр;
КонецФункции	

Функция ОпределитьПараметрыВСтрокеПримера(Знач Стр)
	Массив = Новый Массив;
	
	Стр = СокрЛП(Стр);
	
	Если Лев(Стр,1) <> "|" Тогда
		Возврат Массив;
	КонецЕсли;	 
	
	Если Прав(Стр,1) <> "|" Тогда
		Возврат Массив;
	КонецЕсли;	 
	
	
	Стр = Сред(Стр,2);
	Стр = Сред(Стр,1,СтрДлина(Стр)-1);
	//убрали символы | слева и справа
	
	Стр    = ПодготовитьСтрокуПримераКРазбору(Стр);
	Массив = РазложитьСтрокуВМассивПодстрок(Стр,"|");
	
	
	
	Для Ккк = 0 По Массив.Количество()-1 Цикл
		Массив[Ккк] = СтрЗаменить(Массив[Ккк],ПредставлениеВертЧертыВТабДок,"|");//учли что вертикальная черта может быть в значении
		Массив[Ккк] = СокрЛП(Массив[Ккк]);
	КонецЦикла;
	
	
	Спс = Новый СписокЗначений;
	Для каждого Элем Из Массив Цикл
		Спс.Добавить(Элем);
	КонецЦикла;
	
	Возврат  Спс;
КонецФункции

Процедура ФорматТаблицыПримеров(Тзн,РазныеИменнованныеПараметры,БылаОшибка)
	Если Тзн.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	МассивПараметров = ОпределитьПараметрыВСтрокеПримера(Тзн[0].Стр);
	Для Ккк = 0 По МассивПараметров.Количество()-1 Цикл
		МассивПараметров[Ккк].Значение = СокрЛП(НРег(МассивПараметров[Ккк].Значение));
	КонецЦикла;
	
	//проверим соответствие параметров в шагах и в таблице примеров
	Для каждого ЭлемРазныеИменнованныеПараметры Из РазныеИменнованныеПараметры Цикл
		Если МассивПараметров.НайтиПоЗначению(НРег(ЭлемРазныеИменнованныеПараметры)) = Неопределено Тогда
			БылаОшибка = Истина;
			Сообщить("Параметр " + ЭлемРазныеИменнованныеПараметры + " не найден в таблице параметров!");
		КонецЕсли;
	КонецЦикла;
	
	
	
	
	МассивПараметров = ОпределитьПараметрыВСтрокеПримера(Тзн[0].Стр);
	КолПараметров = МассивПараметров.Количество();
	МассивДлин = Новый Массив;
	Для каждого Элем Из МассивПараметров Цикл
		МассивДлин.Добавить(0);
	КонецЦикла;
	
	
	Для каждого СтрТзн Из Тзн Цикл
		МассивПараметров = ОпределитьПараметрыВСтрокеПримера(СтрТзн.Стр);
		
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			ДлинаСтроки = СтрДлина(СокрЛП(МассивПараметров.Получить(Ккк)));
			Если ДлинаСтроки > МассивДлин[Ккк] Тогда
				МассивДлин[Ккк] = ДлинаСтроки;
			КонецЕсли;	 
			
		КонецЦикла;
	КонецЦикла;
	
	
	Для каждого СтрТзн Из Тзн Цикл
		МассивПараметров = ОпределитьПараметрыВСтрокеПримера(СтрТзн.Стр);
		
		СтрПараметров = "| ";
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			Зн = СокрЛП(МассивПараметров[Ккк]);
			Пока СтрДлина(Зн) < МассивДлин[Ккк] Цикл
				Зн = Зн + " ";
			КонецЦикла;
			СтрПараметров = СтрПараметров + Зн + " | ";
		КонецЦикла;
		
		СтрПараметров = СокрЛП(СтрПараметров);
		
		СтрТзн.Стр = СтрПараметров;
	КонецЦикла;
	
	
КонецПроцедуры

Процедура ОпределитьТипЗначения(Знач Стр,Тип,Значение,ОпределятьСтроку = Ложь)
	ИсходнаяСтрока = Стр;
	ПромМассив     = Новый Массив;
	
	
	ОбработатьСтрокиЭмуляцияRegExp(Стр,ПромМассив,"'");
	Если ПромМассив.Количество() > 0 Тогда
		Тип      = "Строка";
		Значение = ИсходнаяСтрока;
		Возврат;
	КонецЕсли; 
	
	ОбработатьСтрокиЭмуляцияRegExp(Стр,ПромМассив,"""");
	Если ПромМассив.Количество() > 0 Тогда
		Тип      = "Строка";
		Значение = ИсходнаяСтрока;
		Возврат;
	КонецЕсли; 
	
	ОбработатьДатыЭмуляцияRegExp(Стр,ПромМассив);
	Если ПромМассив.Количество() > 0 Тогда
		Тип      = "Дата";
		Значение = ИсходнаяСтрока;
		Возврат;
	КонецЕсли; 
	
	ОбработатьЧислаЭмуляцияRegExp(Стр,ПромМассив);
	Если ПромМассив.Количество() > 0 Тогда
		Тип      = "Число";
		Значение = ИсходнаяСтрока;
		Возврат;
	КонецЕсли; 
	
	Если ОпределятьСтроку Тогда
		Тип      = "Строка";
		Значение = ИсходнаяСтрока;
		Возврат;
	КонецЕсли;  
	
	ВызватьИсключение "Не смог определить тип значения для строки: " + ИсходнаяСтрока;
	
КонецПроцедуры

Функция ЭтоЛюбоеЧисло(Знач Стр)
	КолТочек = 0;
	Длина = СтрДлина(Стр);
	Для Ккк = 1 По Длина Цикл
		Символ = Сред(Стр,Ккк,1);
		Если ЭтоЦелоеЧисло(Символ) Тогда
		ИначеЕсли Символ = "." Тогда	
			КолТочек = КолТочек + 1;
		Иначе
			Возврат Ложь;
		КонецЕсли;	 
	КонецЦикла; 
	
	Если КолТочек > 1 Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Символ = Сред(Стр,1,1);
	Если НЕ ЭтоЦелоеЧисло(Символ) Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Если Символ = "0" Тогда //значит это строка
		Возврат Ложь;
	КонецЕсли;	 
	
	Возврат Истина;
	
КонецФункции	

Функция ЭтоДата(Стр)
	Массив = РазложитьСтрокуВМассивПодстрок(Стр,".");
	Если Массив.Количество() <> 3 Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Элем1 = Массив[0];
	Элем2 = Массив[1];
	Элем3 = Массив[2];
	
	Если НЕ ЭтоЦелоеЧисло(Элем1) Тогда
		Возврат Ложь;
	КонецЕсли;	 
	Если НЕ ЭтоЦелоеЧисло(Элем2) Тогда
		Возврат Ложь;
	КонецЕсли;	 
	Если НЕ ЭтоЦелоеЧисло(Элем3) Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Если СтрДлина(Элем1) <> 2 Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Если СтрДлина(Элем2) <> 2 Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Если (СтрДлина(Элем3) <> 2) и (СтрДлина(Элем3) <> 4) Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	
	
	
	Возврат Истина;
КонецФункции	

Процедура ОпределитьТипЗначенияСтрокиЦеликом(Знач Стр,Тип)
	Тип = "Строка";
	
	Если ЭтоКорректноеЧисло(Стр) Тогда
		Тип = "Число";
	КонецЕсли;	 
	
	Если ЭтоДата(Стр) Тогда
		Тип = "Дата";
	КонецЕсли;	 
	
КонецПроцедуры


Функция УбратьКавычкиСлеваИСправа(Знач Стр)
	Возврат Сред(Стр,2,СтрДлина(Стр)-2);
КонецФункции	

Функция ПреобразоватьИменнованныеПараметрыСОпределениемТипов(Спс,СпсИмен)
	НовыйСписок = Новый СписокЗначений;
	Ном = 0;
	Для каждого Элем Из Спс Цикл
		СтруктураЗначения = Новый Структура;
		
		Значение = Неопределено;
		Тип      = Неопределено;
		ОпределитьТипЗначенияСтрокиЦеликом(Элем.Значение,Тип);
		
		Если Тип = "Строка" Тогда
			Если (Лев(Элем.Значение,1) = """") и (Прав(Элем.Значение,1) = """") Тогда
				Элем.Значение = УбратьКавычкиСлеваИСправа(Элем.Значение);
			ИначеЕсли (Лев(Элем.Значение,1) = "'") и (Прав(Элем.Значение,1) = "'") Тогда
				Элем.Значение = УбратьКавычкиСлеваИСправа(Элем.Значение);
			КонецЕсли;	 
		КонецЕсли;	 
		
		//Сообщить("Элем.Значение="+Элем.Значение + " , Тип="+Тип);
		
		СтруктураЗначения.Вставить("Значение",Элем.Значение);
		СтруктураЗначения.Вставить("Тип",Тип);
		СтруктураЗначения.Вставить("ИмяПараметра",СпсИмен[Ном].Значение);
		
		НовыйСписок.Добавить(СтруктураЗначения);
		
		Ном = Ном + 1;
	КонецЦикла;
	
	Возврат НовыйСписок;
КонецФункции

Функция СоздатьИмяШагаДляScenarioOutline_И_ОбработатьЗначенияПараметров(Знач Стр,ЗначенияПараметровОбычные,ЗначенияПараметровИменованные)
	Для каждого Элем Из ЗначенияПараметровОбычные Цикл
		Если Элем.Значение.Тип = "ПараметрИменованный" Тогда
			
			ИмяПараметра      = Элем.Значение.Значение;
			ЗначениеПараметра = Неопределено;
			ТипПараметра      = Неопределено;
			Для каждого ЗнПарам Из ЗначенияПараметровИменованные Цикл
				Если ЗнПарам.Значение.ИмяПараметра = ИмяПараметра Тогда
					ЗначениеПараметра = ЗнПарам.Значение.Значение;
					ТипПараметра      = ЗнПарам.Значение.Тип;
				КонецЕсли; 
			КонецЦикла;
			
			Если ЗначениеПараметра = Неопределено Тогда
				СтрОшибки = "Не смог найти  в массиве ЗначенияПараметровИменованные элемент с именем " + ИмяПараметра;
				Сообщить(СтрОшибки);
				ВызватьИсключение СтрОшибки;
			КонецЕсли; 
			
			
			
			Стр = СтрЗаменить(Стр,"<"+ ИмяПараметра + ">",ЗначениеПараметра);
			
			Элем.Значение.Значение = ЗначениеПараметра;
			Элем.Значение.Тип      = ТипПараметра;
			
		КонецЕсли; 
	КонецЦикла;
	
	Возврат Стр;
КонецФункции

Функция СкопироватьСписокЗначенийСтруктур(Массив)
	НовыйСписок = Новый СписокЗначений;
	
	Для каждого ЭлемМассив Из Массив Цикл
		НоваяСтруктура = Новый Структура;
		Для каждого ЭлемСтруктура Из ЭлемМассив.Значение Цикл
			НоваяСтруктура.Вставить(ЭлемСтруктура.Ключ,ЭлемСтруктура.Значение);
		КонецЦикла;
		
		НовыйСписок.Добавить(НоваяСтруктура);
	КонецЦикла;
	
    Возврат НовыйСписок;
КонецФункции

Процедура ДобавитьСценарийДляДанногоПримера(СтрокаПримеров)
	//СтрШагПримера = СтрокаПримеров.Строки.Добавить();
	
	СтрокиШагов = СтрокаПримеров.Родитель.Родитель;
	Для каждого СтрСтрокиШагов Из СтрокиШагов.Строки Цикл
		Если СтрСтрокиШагов.Примеры = Истина Тогда
			//это служебная строка
			Продолжить;
		КонецЕсли; 
		
		ЗначенияПараметров = СкопироватьСписокЗначенийСтруктур(СтрСтрокиШагов.ЗначенияПараметров);
		ИмяШага            = СоздатьИмяШагаДляScenarioOutline_И_ОбработатьЗначенияПараметров(СтрСтрокиШагов.Имя,ЗначенияПараметров,СтрокаПримеров.ИменованныеПараметры);
		
		СтрШагПримера                    = СтрокаПримеров.Строки.Добавить();
		ЗаполнитьЗначенияСвойств(СтрШагПримера,СтрСтрокиШагов);
		
		//надо заменить только имя шага (с учетом реальных параметров) и значения параметров
		СтрШагПримера.Имя                = ИмяШага;
		СтрШагПримера.ЗначенияПараметров = ЗначенияПараметров;
	КонецЦикла;
КонецПроцедуры


Функция ПолучитьНовыйStepDefinition(Знач Стр)
	
	Стр = СтрЗаменить(Стр,"СтрокаК)",")");
	Стр = СтрЗаменить(Стр,"СтрокаА)",")");
	Стр = СтрЗаменить(Стр,"Дата)",")");
	Стр = СтрЗаменить(Стр,"Число)",")");
	
	Стр = СтрЗаменить(Стр,"СтрокаК,",",");
	Стр = СтрЗаменить(Стр,"СтрокаА,",",");
	Стр = СтрЗаменить(Стр,"Дата,",",");
	Стр = СтрЗаменить(Стр,"Число,",",");
	
	Возврат Стр;
КонецФункции

Функция ПолучитьНовуюСтрокуПараметров(Знач Стр)
	Стр = Стр + ",";
	
	Стр = СтрЗаменить(Стр,"Строка,",",");
	Стр = СтрЗаменить(Стр,"Дата,",",");
	Стр = СтрЗаменить(Стр,"Число,",",");
	
	Стр = Лев(Стр,СтрДлина(Стр)-1);
	
	Возврат Стр;
КонецФункции

Функция СкопироватьСтруктуру(Оригинал)
	Результат = Новый Структура();
	Для каждого Элем Из Оригинал Цикл
		Результат.Вставить(Элем.Ключ,Элем.Значение);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции	


Процедура ЗакрытьПредыдущийСценарий(ИмяФичи,ПолноеИмяФичи,ТекущийТипСценария,ПредыдущееКлючевоеСлово,ТекущееКлючевоеСлово,ДеревоСтроки,ОписаниеСценария,ТаблицаШагов,ТаблицаИзвестныхStepDefinition,ТаблицаСтрокПримеров,НомерСтрокиСценария,ТаблицаУжеСуществующихСценариев,СтруктураПараметров,МассивСценариевЗащитаОтЗацикливанияКеш = Неопределено)
	
	//Сообщить("ЗакрытьПредыдущийСценарий");
	
	Если (ТекущееКлючевоеСлово <> "scenario") и (ТекущееКлючевоеСлово <> "scenario_outline") Тогда
		Возврат;
	КонецЕсли;	 
	
	ИмяСценария = ОписаниеСценария;
	Если ТекущийТипСценария = "background" Тогда
		ИмяСценария = "Контекст";
	КонецЕсли;	 
	
	Если (ТекущийТипСценария = "background") или (ТекущийТипСценария = "scenario") или (ТекущийТипСценария = "scenario_outline") Тогда
		СтрДеревоСтроки = ДеревоСтроки.Добавить();
		СтрДеревоСтроки.Имя = ИмяСценария;
		СтрДеревоСтроки.Сценарий = Истина;
		СтрДеревоСтроки.ТипКартинки = 2;
		Если ТекущийТипСценария = "background" Тогда
			СтрДеревоСтроки.ТипКартинки = 7;
		КонецЕсли; 
		СтрДеревоСтроки.ПолныйПуть = СтрДеревоСтроки.Родитель.ПолныйПуть + ":" + НомерСтрокиСценария;
		Если ТекущийТипСценария = "background" Тогда
			СтрДеревоСтроки.ЭтоКонтекст = Истина;
		КонецЕсли;	 
		
		СтрокиШагов = СтрДеревоСтроки.Строки;
		
		РазныеИменнованныеПараметры = Новый Массив;
		
		Для каждого СтрТаблицаШагов Из ТаблицаШагов Цикл
			
			Если СтрТаблицаШагов.ИмяОбласти <> Неопределено Тогда
				
				Если СтрТаблицаШагов.НачалоОбласти Тогда
					СтрОбласть         = СтрокиШагов.Добавить();
					СтрОбласть.Имя     = СтрТаблицаШагов.ИмяОбласти;
					СтрОбласть.Область = Истина;
					СтрОбласть.ТипКартинки = -1;
					
					СтрокиШагов = СтрОбласть.Строки;
				КонецЕсли;	 
				
				Если НЕ СтрТаблицаШагов.НачалоОбласти Тогда
					СтрокиШагов = СтрокиШагов.Родитель.Родитель.Строки;
				КонецЕсли;	 
				
				Продолжить;
			КонецЕсли;	 
			
			СтрСтрокиШагов     = СтрокиШагов.Добавить();
			СтрСтрокиШагов.Имя = СтрТаблицаШагов.ИмяШага;
			СтрСтрокиШагов.Шаг = Истина;
			СтрСтрокиШагов.ТипКартинки = 3;
			СтрСтрокиШагов.ПолныйПуть  = "     " + СтрДеревоСтроки.Родитель.ПолныйПуть + ":" + СтрТаблицаШагов.НомерСтроки;
			
			
			
			ТаблицаСтрокПередачаПараметровТаблицей = СтрТаблицаШагов.ТаблицаСтрокПередачаПараметровТаблицей;
			Если ТаблицаСтрокПередачаПараметровТаблицей.Количество() > 0 Тогда
				БылаОшибка = Ложь;
				ФорматТаблицыПримеров(ТаблицаСтрокПередачаПараметровТаблицей,РазныеИменнованныеПараметры,БылаОшибка);
				
				СтрСтрокиШагов.ШагСПараметрамиВТаблице       = Истина;
				СтрокиТаблицаСтрокПередачаПараметровТаблицей = СтрСтрокиШагов.Строки;
				
				Для каждого СтрТаблицаСтрокПередачаПараметровТаблицей Из ТаблицаСтрокПередачаПараметровТаблицей Цикл
					СтрокаТаблицы                                  = СтрокиТаблицаСтрокПередачаПараметровТаблицей.Добавить();
					СтрокаТаблицы.СтрокаПараметровШагаВВидеТаблицы = Истина;
					СтрокаТаблицы.Имя                              = СтрТаблицаСтрокПередачаПараметровТаблицей.Стр;
					СтрокаТаблицы.ПараметрыТаблицы                 = ОпределитьПараметрыВСтрокеПримера(СтрТаблицаСтрокПередачаПараметровТаблицей.Стр);
					//СтрокаТаблицы.ПараметрыТаблицы                 = ПреобразоватьИменнованныеПараметрыСОпределениемТипов(СтрокаТаблицы.ПараметрыТаблицы,СтрокаТаблицы.ПараметрыТаблицы);
					СтрокаТаблицы.ПараметрыТаблицы                 = ПреобразоватьИменнованныеПараметрыСОпределениемТипов(СтрокаТаблицы.ПараметрыТаблицы,СтрокаТаблицы.ПараметрыТаблицы);
					СтрокаТаблицы.ТипКартинки                      = -1;
				КонецЦикла;
			КонецЕсли;	 
			
			
			
			//ЗначенияПараметров = Новый Массив;
			ЗначенияПараметров = Новый СписокЗначений;
			СтараяСтрокаПараметров = "";
			СтарыйStepDefinition   = ПолучитьStepDefinitionПоСтроке(СтрТаблицаШагов.ИмяШагаБезКлючевогоСлова, ЗначенияПараметров, СтараяСтрокаПараметров,СтрСтрокиШагов.ШагСПараметрамиВТаблице);
			НовыйStepDefinition    = ПолучитьНовыйStepDefinition(СтарыйStepDefinition);
			НоваяСтрокаПараметров  = ПолучитьНовуюСтрокуПараметров(СтараяСтрокаПараметров);
			
			
			
			
			
			СтрСтрокиШагов.ЗначенияПараметров = ЗначенияПараметров;
			
			Для каждого ЭлемЗначенияПараметров Из ЗначенияПараметров Цикл
				Если ЭлемЗначенияПараметров.Значение.Тип = "ПараметрИменованный" Тогда
					Если РазныеИменнованныеПараметры.Найти(ЭлемЗначенияПараметров.Значение.Значение) = Неопределено Тогда
						РазныеИменнованныеПараметры.Добавить(ЭлемЗначенияПараметров.Значение.Значение);
					КонецЕсли; 
				КонецЕсли; 
			КонецЦикла;
			
			
			
			
			
			
			НашелStepDefinitionВepf = Ложь;
			
			ИмяПроцедурыИзStepDefinition = Лев(НовыйStepDefinition,Найти(НовыйStepDefinition,"(")-1);
			
			Если Не НашелStepDefinitionВepf Тогда
				СтрТаблицаИзвестныхStepDefinition = ТаблицаИзвестныхStepDefinition.Найти(ИмяПроцедурыИзStepDefinition,"СтрокаРеальнойПроцедуры");
				Если СтрТаблицаИзвестныхStepDefinition <> Неопределено Тогда
					СтрСтрокиШагов.Снипет   = НовыйStepDefinition;
					НашелStepDefinitionВepf = Истина;
				КонецЕсли;	 
			КонецЕсли;  
			
			
			
			Если Не НашелStepDefinitionВepf Тогда
				СтрТаблицаИзвестныхStepDefinition = ТаблицаИзвестныхStepDefinition.Найти(НРег(СтарыйStepDefinition),"ID");
				Если СтрТаблицаИзвестныхStepDefinition <> Неопределено Тогда
					СтрСтрокиШагов.Снипет   = СтарыйStepDefinition;
					НашелStepDefinitionВepf = Истина;
				КонецЕсли;	 
			КонецЕсли;  
			
			
			Если НашелStepDefinitionВepf Тогда
				СтрСтрокиШагов.АдресСнипета            = СтрТаблицаИзвестныхStepDefinition.ИмяФайла;
				СтрСтрокиШагов.СтрокаРеальнойПроцедуры = СтрТаблицаИзвестныхStepDefinition.СтрокаРеальнойПроцедуры;
				
				
				СтрЗамены = НРег("\" + ИмяФичи + ".feature");
				ПутьФичи  = СтрЗаменить(НРег(ПолноеИмяФичи),СтрЗамены,"");
				Если Найти(НРег(СтрТаблицаИзвестныхStepDefinition.ИмяФайла),ПутьФичи) = 0 Тогда
					СтрСтрокиШагов.ЭтоЧужойСнипет = Истина;
				КонецЕсли; 
				ФайлОбработки = Новый Файл(СтрТаблицаИзвестныхStepDefinition.ИмяФайла);
				Если НРег(ИмяФичи) <> НРег(ФайлОбработки.ИмяБезРасширения) Тогда
					СтрСтрокиШагов.ЭтоЧужойСнипет = Истина;
				КонецЕсли;
			Иначе
				//Сообщить("Не нашел " + НовыйStepDefinition);
				
				СтрТаблицаУжеСуществующихСценариев = ТаблицаУжеСуществующихСценариев.Найти(СтрТаблицаШагов.ИмяШагаБезКлючевогоСлова,"ИмяСценария");
				Если СтрТаблицаУжеСуществующихСценариев = Неопределено Тогда
					СтрСтрокиШагов.Снипет                  = НовыйStepDefinition;
					СтрСтрокиШагов.СтрокаРеальнойПроцедуры = СтрЗаменить(НовыйStepDefinition, "("+НоваяСтрокаПараметров+")", "");
				Иначе
					//это подчиненное дерево
					
					
					Если МассивСценариевЗащитаОтЗацикливанияКеш = Неопределено Тогда
						МассивСценариевЗащитаОтЗацикливанияКеш = Новый Массив;
					КонецЕсли; 
					
					Элем = МассивСценариевЗащитаОтЗацикливанияКеш.Найти(СтрТаблицаУжеСуществующихСценариев.ИмяСценария);
					Если Элем <> Неопределено Тогда
						//значит этот сценарий уже вызывался выше и сейчас произойдёт зацикливание
						Сообщить("Не смог скопировать сценарий " + СтрТаблицаУжеСуществующихСценариев.ИмяСценария + ", т.к. произошло бы зацикливание.");
						Возврат;
					КонецЕсли; 
					
					МассивСценариевЗащитаОтЗацикливанияКеш.Добавить(СтрТаблицаУжеСуществующихСценариев.ИмяСценария);
					
					
					СтрСтрокиШагов.Шаг          = Ложь;
					СтрСтрокиШагов.ШагСценарий  = Истина;
					СтрСтрокиШагов.ТипКартинки = -1;
					СтрСтрокиШагов.АдресСнипета = СтрТаблицаУжеСуществующихСценариев.ИмяФайла;
					
					
					
					
					//Сообщить("Загрузим эту фичу в промежуточное дерево. " + СтрТаблицаУжеСуществующихСценариев.ИмяФайла);
					
					
					
					//Загрузим эту фичу в промежуточное дерево
					
					
					КешФич = СтруктураПараметров.КешФич;
					
					СтрКешФич = КешФич.Найти(СтрТаблицаУжеСуществующихСценариев.ИмяФайла,"ИмяФайла");
					Если СтрКешФич = Неопределено Тогда
						ПромДерево       = СоздатьДеревоЗначений();
						ПромДеревоСтроки = ПромДерево.Строки;
						
						ПромСтрокаФичи   = ПромДеревоСтроки.Добавить();
						ПромСтрокаФичи.Фича = Истина;
						ПромСтрокаФичи.Имя  = СтрТаблицаУжеСуществующихСценариев.ИмяФайла;
						ПромСтрокаФичи.ПолныйПуть = СтрТаблицаУжеСуществующихСценариев.ИмяФайла;
						
						КопияСтруктураПараметров = СкопироватьСтруктуру(СтруктураПараметров);
						КопияСтруктураПараметров.ИдетЗагрузкаИзКаталога = Ложь;
						
						
						ДвДанныеФичи = СтрТаблицаУжеСуществующихСценариев.ДвоичныеДанные;
						ИмяВременнойФичи = ПолучитьИмяВременногоФайла("feature");
						ДвДанныеФичи.Записать(ИмяВременнойФичи);
						
						
						//МассивСценариевЗащитаОтЗацикливанияКешКопия = СкопироватьМассив(МассивСценариевЗащитаОтЗацикливанияКеш);
						
						ОписаниеОшибки = "";
						Если Не ПроверитьФичуНаКорректностьСинтаксисаИЗагрузитьСценарии(ИмяВременнойФичи,ОписаниеОшибки,ПромСтрокаФичи.Строки,ТаблицаИзвестныхStepDefinition,КопияСтруктураПараметров,МассивСценариевЗащитаОтЗацикливанияКеш) Тогда
							Сообщить("Не смог загрузить " + СтрТаблицаУжеСуществующихСценариев.ИмяФайла + ". " + ОписаниеОшибки);
							Возврат;
						КонецЕсли;	 
						
						СтрКешФич          = КешФич.Добавить();
						СтрКешФич.Дерево   = ПромДерево;
						СтрКешФич.ИмяФайла = СтрТаблицаУжеСуществующихСценариев.ИмяФайла;
					Иначе
						ПромДерево = СтрКешФич.Дерево;
					КонецЕсли;	 
					
					МассивСценариевЗащитаОтЗацикливанияКеш.Удалить(МассивСценариевЗащитаОтЗацикливанияКеш.Количество()-1);
					
					
					СкопироватьСтрокиСценарияВУказаннуюСтроку(СтрСтрокиШагов,ПромДерево,СтрТаблицаУжеСуществующихСценариев.ИмяСценария,СтрТаблицаУжеСуществующихСценариев.ИмяФайла);
					
					
					//ТаблицаШагов = СтрТаблицаУжеСуществующихСценариев.ТаблицаШагов;
					//Для каждого Элем Из ТаблицаШагов Цикл
					//КонецЦикла;
				КонецЕсли;	 
				
				//ВтораяЧастьСтрокиПозиция = 1;
				//ТекущееКлючевоеСлово = ПолучитьКлючевоеСлово(НРег(Стр), ПредыдущееКлючевоеСлово, ВтораяЧастьСтрокиПозиция);
				//ИмяШага = Стр;
				//Если Лев(НРег(ИмяШага),9) = "сценарий:" Тогда
				//	ИмяШага = СокрЛП(Сред(ИмяШага,10));
				//КонецЕсли;	 
				//ВтораяЧастьСтроки = СокрЛП(Сред(Стр, ВтораяЧастьСтрокиПозиция));
				
			КонецЕсли;  
			
			СтрСтрокиШагов.ИмяШагаБезКлючевогоСлова   = СтрТаблицаШагов.ИмяШагаБезКлючевогоСлова;
			
		КонецЦикла;
		
		БылаОшибка = Ложь;
		ФорматТаблицыПримеров(ТаблицаСтрокПримеров,РазныеИменнованныеПараметры,БылаОшибка);
		//ФорматТаблицыПримеров(ТаблицаСтрокПередачаПараметровТаблицей,РазныеИменнованныеПараметры,БылаОшибка);
		Если БылаОшибка Тогда
			СтрОшибки = "Ошибка парсинга фичи " + ДеревоСтроки.Родитель.Имя + "! Сценарий: " + ОписаниеСценария;
			Сообщить(СтрОшибки);
			ВызватьИсключение СтрОшибки;
		КонецЕсли; 
		
		Если ТаблицаСтрокПримеров.Количество() > 0 Тогда
			СтрДеревоСтроки.ЭтоScenarioOutline = Истина;
			
			СтрДеревоСтроки = СтрокиШагов.Добавить();
			СтрДеревоСтроки.Имя         = "Примеры";
			СтрДеревоСтроки.Примеры     = Истина;
			СтрДеревоСтроки.ТипКартинки = -1;
			//СтрДеревоСтроки.ПолныйПуть = СтрДеревоСтроки.Родитель.ПолныйПуть + ":" + НомерСтрокиСценария;
			
			СтрокиПримеров = СтрДеревоСтроки.Строки;
			Ном = 0;
			Для каждого СтрТаблицаСтрокПримеров Из ТаблицаСтрокПримеров Цикл
				Ном = Ном + 1;
				Если Ном = 1 Тогда
					//в первой строке лежат имена параметров
					СтрДеревоСтроки.ИменованныеПараметры = ОпределитьПараметрыВСтрокеПримера(СтрТаблицаСтрокПримеров.Стр);
				КонецЕсли; 
				
				СтрСтрокаПримеров             = СтрокиПримеров.Добавить();
				СтрСтрокаПримеров.Имя         = СтрТаблицаСтрокПримеров.Стр;
				СтрСтрокаПримеров.Пример      = Истина;
				СтрСтрокаПримеров.ТипКартинки = -1;
				
				Если Ном > 1 Тогда
					//тут будут лежать конкретные значения параметров
					СтрСтрокаПримеров.ИменованныеПараметры = ОпределитьПараметрыВСтрокеПримера(СтрТаблицаСтрокПримеров.Стр);
					//Нужно определить типы значений
					СтрСтрокаПримеров.ИменованныеПараметры = ПреобразоватьИменнованныеПараметрыСОпределениемТипов(СтрСтрокаПримеров.ИменованныеПараметры,СтрДеревоСтроки.ИменованныеПараметры);
					
					ДобавитьСценарийДляДанногоПримера(СтрСтрокаПримеров);
				КонецЕсли; 
			КонецЦикла;
		КонецЕсли;	 
		
		
		ТаблицаШагов.Очистить();
		ТаблицаСтрокПримеров.Очистить();
	КонецЕсли;	 
КонецПроцедуры

Функция СкопироватьМассив(Ориг)
	Рез = Новый Массив;
	Для каждого Элем Из Ориг Цикл
		Рез.Добавить(Элем);
	КонецЦикла;
	
	Возврат Рез;
КонецФункции	

Процедура СкопироватьСтрокиСценарияВУказаннуюСтроку(КудаКопировать,ДеревоОткудаКопировать,ИмяСценария,ИмяФайла)
	СтрокаСценария = Неопределено;
	
	МассивСценариевЗащитаОтЗацикливания = КудаКопировать.МассивСценариевЗащитаОтЗацикливания;
	Если МассивСценариевЗащитаОтЗацикливания = Неопределено Тогда
		МассивСценариевЗащитаОтЗацикливания = Новый Массив();
		КудаКопировать.МассивСценариевЗащитаОтЗацикливания = МассивСценариевЗащитаОтЗацикливания;
	КонецЕсли; 
	
	Элем = МассивСценариевЗащитаОтЗацикливания.Найти(ИмяСценария);
	Если Элем <> Неопределено Тогда
		//значит этот сценарий уже вызывался выше и сейчас произойдёт зацикливание
		Сообщить("Не смог скопировать сценарий " + ИмяСценария + ", т.к. произошло бы зацикливание.");
		Возврат;
	КонецЕсли; 
	
	МассивСценариевЗащитаОтЗацикливания.Добавить(ИмяСценария);
	
	
	ПараметрыОтбора = Новый Структура();
	ПараметрыОтбора.Вставить("Имя",ИмяСценария);
	НайденныеСтроки = ДеревоОткудаКопировать.Строки.НайтиСтроки(ПараметрыОтбора,Истина);
	
	СтрокаОткудаКопировать = Неопределено;
	КолСценариев           = 0;
	Для каждого СтрокаДерева Из НайденныеСтроки Цикл
		Если СтрокаДерева.Сценарий = Истина Тогда
			КолСценариев = КолСценариев + 1;
			СтрокаОткудаКопировать = СтрокаДерева;
		КонецЕсли;	 
	КонецЦикла;
	
	
	Если КолСценариев <> 1 Тогда
		Сообщить("Ошибка! В фиче " + ИмяФайла + " было найдено несколько сценариев с именем " + ИмяСценария);
		Возврат;
	КонецЕсли;	 
	
	
	СкопироватьСтрокуВДереваПодчиненныеЭлементы(КудаКопировать,СтрокаОткудаКопировать);
	
КонецПроцедуры

Процедура СкопироватьСтрокуВДереваПодчиненныеЭлементы(КудаКопировать,ОткудаКопировать)
	Для каждого СтрОткудаКопировать Из ОткудаКопировать.Строки Цикл
		СтрокаКуда = КудаКопировать.Строки.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаКуда,СтрОткудаКопировать);
		
		//подчиненный элемент получил МассивСценариевЗащитаОтЗацикливания
		СтрокаКуда.МассивСценариевЗащитаОтЗацикливания = КудаКопировать.МассивСценариевЗащитаОтЗацикливания;
		
		СкопироватьСтрокуВДереваПодчиненныеЭлементы(СтрокаКуда,СтрОткудаКопировать);
	КонецЦикла;
КонецПроцедуры

Процедура НайтиСтрокуСценарияВДеревеПоИмени(Дерево,ИмяСценария,СтрокаСценария)
	
	
КонецПроцедуры

Функция ПолучитьСледующееОжидаемоеКлючевоеСлово(Стр,ТекущийТипСценария,ИдетЧтениеПримеров)
	СледующаяСтрокаМожетБыть = "";
	
	Если Стр = "feature" Тогда
		СледующаяСтрокаМожетБыть = "background,scenario,scenario_outline";
		ИдетЧтениеПримеров = Ложь;
	КонецЕсли;	 
	
	Если Стр = "background" Тогда
		ТекущийТипСценария = "background";
		СледующаяСтрокаМожетБыть = "when,given,then,and,but";
		ИдетЧтениеПримеров = Ложь;
	КонецЕсли;	 
	
	Если Стр = "scenario" Тогда
		ТекущийТипСценария = "scenario";
		СледующаяСтрокаМожетБыть = "when,given,then,and,but";
		ИдетЧтениеПримеров = Ложь;
	КонецЕсли;	 
	
	Если Стр = "scenario_outline" Тогда
		ТекущийТипСценария = "scenario_outline";
		СледующаяСтрокаМожетБыть = "when,given,then,and,but";
		ИдетЧтениеПримеров = Ложь;
	КонецЕсли;	 
	
	
	Если Стр = "given" Тогда
		Если ТекущийТипСценария = "background" Тогда
			СледующаяСтрокаМожетБыть = "when,then,and,but,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario_outline" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,examples";
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если (Стр = "and") или (Стр = "but") Тогда
		Если ТекущийТипСценария = "background" Тогда
			СледующаяСтрокаМожетБыть = "when,then,and,but,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario" Тогда
			СледующаяСтрокаМожетБыть = "when,then,and,but,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario_outline" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,examples";
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Стр = "when" Тогда
		Если ТекущийТипСценария = "background" Тогда
			СледующаяСтрокаМожетБыть = "when,then,and,but,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario_outline" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,examples";
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Стр = "then" Тогда
		Если ТекущийТипСценария = "background" Тогда
			СледующаяСтрокаМожетБыть = "when,then,and,but,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,scenario,scenario_outline";
		ИначеЕсли ТекущийТипСценария = "scenario_outline" Тогда
			СледующаяСтрокаМожетБыть = "when,then,but,and,given,examples";
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Стр = "examples" Тогда
		ИдетЧтениеПримеров = Истина;
		СледующаяСтрокаМожетБыть = "scenario,scenario_outline";
	КонецЕсли;	 
	
	Если СледующаяСтрокаМожетБыть = Неопределено Тогда
		Сообщить("Не смог определить СледующееОжидаемоеКлючевое по: " + Стр);
	КонецЕсли;	 
	
	Возврат СледующаяСтрокаМожетБыть;
КонецФункции

Функция ТекущееКлючевоеСловоСоответствуетОжидаемому(ТекущееКлючевоеСлово,ОжидаемоеКлючевоеСлово)
	Если ТекущееКлючевоеСлово = "" Тогда
		Возврат Ложь;
	КонецЕсли; 
	
	Поз = Найти(ОжидаемоеКлючевоеСлово,ТекущееКлючевоеСлово);
	Если Поз > 0 Тогда
		Возврат Истина;
	Иначе
		Возврат Ложь;	
	КонецЕсли;	 
КонецФункции


Функция СоздатьТаблицуШагов()
	Тзн = Новый Массив;
	Возврат Тзн;
КонецФункции

Процедура ДобавитьШаг(ТаблицаШагов,ИмяШагаБезКлючевогоСлова,ИмяШага,НомерСтроки,ТаблицаСтрокПередачаПараметровТаблицей,СруктураОбласти = Неопределено)
	
	СтруктураШага = Новый Структура;
	СтруктураШага.Вставить("ИмяШагаБезКлючевогоСлова",ИмяШагаБезКлючевогоСлова);
	СтруктураШага.Вставить("ИмяШага",ИмяШага);
	СтруктураШага.Вставить("НомерСтроки",НомерСтроки);
	СтруктураШага.Вставить("ТаблицаСтрокПередачаПараметровТаблицей",ТаблицаСтрокПередачаПараметровТаблицей);
	
	СтруктураШага.Вставить("ИмяОбласти",Неопределено);
	СтруктураШага.Вставить("НачалоОбласти",Неопределено);
	Если СруктураОбласти <> Неопределено Тогда
		СтруктураШага.Вставить("ИмяОбласти",СруктураОбласти.ИмяОбласти);
		СтруктураШага.Вставить("НачалоОбласти",СруктураОбласти.НачалоОбласти);
	КонецЕсли;	 
	
	ТаблицаШагов.Добавить(СтруктураШага);
	
	//СтрТаблицаШагов = ТаблицаШагов.Добавить();
	//СтрТаблицаШагов.ИмяШага = ИмяШага;
КонецПроцедуры


Функция СоздатьТаблицуСтрокПримеров()
	Тзн = Новый Массив;
	Возврат Тзн;
КонецФункции

Функция ЗагрузитьФичуВТаблицуЗначений(ИмяФайла,НадоСтроитьДерево)
	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("Стр");
	Тзн.Колонки.Добавить("ЗначениеОтступа");
	Тзн.Колонки.Добавить("СледующийОступ");
	Тзн.Колонки.Добавить("ПредыдущийОтступ");
	Тзн.Колонки.Добавить("НомСтр");
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	
	НомСтр = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		
		
		Если НРег(СокрЛП(Стр)) = "@tree" Тогда
			НадоСтроитьДерево = Истина;
		КонецЕсли;	 
		
		СтрТзн = Тзн.Добавить();
		СтрТзн.Стр = Стр;
		
		НомСтр        = НомСтр + 1;
		СтрТзн.НомСтр = НомСтр;
	КонецЦикла;	
	
	Текст.Закрыть();
	
	
	
	ПредыдущийОтступ = 0;
	Если НадоСтроитьДерево Тогда
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяФайла,"UTF-8");
		
		Ном = -1;
		Пока Истина Цикл
			Ном = Ном + 1;
			
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			
			
			СтрТзн                  = Тзн[Ном];
			СтрТзн.ЗначениеОтступа  = ВычислитьЗначениеОтступа(СтрТзн.Стр,ПредыдущийОтступ);
			СтрТзн.ПредыдущийОтступ = ПредыдущийОтступ;
			СтрТзн.СледующийОступ   = СтрТзн.ЗначениеОтступа;
			
			Если Ном > 0 Тогда
				Тзн[Ном-1].СледующийОступ = СтрТзн.ЗначениеОтступа;
			КонецЕсли;	 
			
			
			ПредыдущийОтступ        = СтрТзн.ЗначениеОтступа;
		КонецЦикла;	
		
		Текст.Закрыть();
		
		КолСтрок = Тзн.Количество()-1;
		Для Ккк = 0 По КолСтрок-1 Цикл
			ТекСтрокаТзн  = Тзн[КолСтрок - Ккк];
			ПредСтрокаТзн = Тзн[КолСтрок - Ккк - 1];
			
			ТекСтрокаСтр  = ТекСтрокаТзн.Стр;
			ПредСтрокаСтр = ПредСтрокаТзн.Стр;
			
			//для пустых строк отступ приравнивается снизу вверх
			Если СокрЛП(ПредСтрокаСтр) = "" Тогда
				ПредСтрокаТзн.ЗначениеОтступа = ТекСтрокаТзн.ЗначениеОтступа;
			КонецЕсли;	
			
			ПредСтрокаТзн.СледующийОступ = ТекСтрокаТзн.ЗначениеОтступа;
		
		КонецЦикла;
		
	КонецЕсли;	 
	
	
	
	Возврат Тзн;
КонецФункции	

Функция ВычислитьЗначениеОтступа(Знач Стр,ПредыдущийОтступ)
	Если Лев(СокрЛП(Стр),1) = "|" Тогда
		//чтобы строки обозначающие таблицы всегда шли как следущая строка
		Возврат ПредыдущийОтступ;
	КонецЕсли;	 
	
	Если Лев(СокрЛП(Стр),1) = "#" Тогда
		Возврат ПредыдущийОтступ;
	КонецЕсли;	 
	
	Если Лев(СокрЛП(Стр),1) = "@" Тогда
		Возврат ПредыдущийОтступ;
	КонецЕсли;	 
	
	Если СокрЛП(Стр) = "" Тогда
		Возврат ПредыдущийОтступ;
	КонецЕсли;	 
	
	Стр = СтрЗаменить(Стр," ","");
	
	Кол = 0;
	Для Ккк = 1 По СтрДлина(Стр) Цикл
		Символ = Сред(Стр,Ккк,1);
		Если Символ = Символы.Таб Тогда
			Кол = Кол + 1;
		Иначе
			Прервать;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Кол;
	
КонецФункции	

Функция СоздатьСтруктуруДляСценария(Имя,ИмяФайла)
	Структура = Новый Структура("", );
	Структура.Вставить("Имя",Имя);
	Структура.Вставить("ИмяФайла",ИмяФайла);
	
	Возврат Структура;
КонецФункции	

Процедура ДобавитьКолонкуСнипетаВТаблицаУжеСуществующихСценариев(ТаблицаУжеСуществующихСценариев)
	
	КолонкаСнипет = ТаблицаУжеСуществующихСценариев.Колонки.Найти("Снипет");
	Если КолонкаСнипет <> Неопределено Тогда
		Возврат;
	КонецЕсли;	 
	
	ТаблицаУжеСуществующихСценариев.Колонки.Добавить("Снипет");
	
	Для каждого СтрТаблицаУжеСуществующихСценариев Из ТаблицаУжеСуществующихСценариев Цикл
		ЗначенияПараметров   = Новый Массив;
		СтарыйStepDefinition = ПолучитьStepDefinitionПоСтроке(СтрТаблицаУжеСуществующихСценариев.ИмяСценария,ЗначенияПараметров);
		НовыйStepDefinition    = ПолучитьНовыйStepDefinition(СтарыйStepDefinition);
		
		//Сообщить("НовыйStepDefinition="+НовыйStepDefinition);
		
		СтрТаблицаУжеСуществующихСценариев.Снипет = НовыйStepDefinition;
	КонецЦикла;
	
	
КонецПроцедуры

Функция ПреобразоватьСписокЗначенийНСтр(Спс)
	Копия = Спс.Скопировать();
	Для каждого Элем Из Копия Цикл
		Элем.Значение = НРег(Элем.Значение);
	КонецЦикла;
	
	Возврат Копия;
КонецФункции	

Функция ПроверитьФичуНаКорректностьСинтаксисаИЗагрузитьСценарии(ИмяФайла,ОписаниеОшибки,ДеревоСтроки = Неопределено,ТаблицаИзвестныхStepDefinition,СтруктураПараметров,МассивСценариевЗащитаОтЗацикливанияКеш = Неопределено)
	Перем ТэгУказанияЯзыка;
	
	
	СписокТеговИсключение           = ПреобразоватьСписокЗначенийНСтр(СтруктураПараметров.СписокТеговИсключение);
	СписокТеговОтбор                = ПреобразоватьСписокЗначенийНСтр(СтруктураПараметров.СписокТеговОтбор);
	ТаблицаУжеСуществующихСценариев = СтруктураПараметров.ТаблицаУжеСуществующихСценариев;
	
	
	
	ТекущийТипСценария      = Неопределено;
	ПредыдущееКлючевоеСлово = Неопределено;
	ОжидаемоеКлючевоеСлово  = "feature";
	ТекущееКлючевоеСлово    = Неопределено;
	ВтораяЧастьСтроки       = Неопределено;
	ОписаниеФичи            = "";
	ОписаниеСценария        = "";
	СтрокаШага              = "";
	ИдетЧтениеПримеров      = Ложь;
	ИдетПередачаПараметровТаблицей = Ложь;
	
	ТаблицаШагов                           = СоздатьТаблицуШагов();
	ТаблицаСтрокПримеров                   = СоздатьТаблицуСтрокПримеров();
	ТаблицаСтрокПередачаПараметровТаблицей = СоздатьТаблицуСтрокПримеров();
	
	ТэгУказанияЯзыка 		= "language:";
	ТекущийЯзыкФичаФайла = "ru";
	
	ФайлФичи = Новый Файл(ИмяФайла);
	ИмяФичи  = ФайлФичи.ИмяБезРасширения;
	
	
	НадоСохранятьДвоичныеДанные = СтруктураПараметров.Свойство("МассивРезультатОбходаКаталогов");
	ФайлВременнаяФича = ИмяФайла;
	Если НадоСохранятьДвоичныеДанные Тогда
		МассивРезультатОбходаКаталогов = СтруктураПараметров.МассивРезультатОбходаКаталогов;
		Для каждого Элем Из МассивРезультатОбходаКаталогов Цикл
			Если Не Элем.Свойство("Фича") Тогда
				Продолжить;
			КонецЕсли;	 
			
			Если НРег(Элем.ПолныйПуть) = НРег(ИмяФайла) Тогда
				ФайлВременнаяФича = ПолучитьИмяВременногоФайла("feature");
				Элем.ДвоичныеДанные.Записать(ФайлВременнаяФича);
			КонецЕсли;	 
		КонецЦикла;
	КонецЕсли;	 
	
	
	НадоСтроитьДерево        = Ложь;
	ТаблицаТекстФичи         = ЗагрузитьФичуВТаблицуЗначений(ФайлВременнаяФича,НадоСтроитьДерево);
	КолСтрокТаблицаТекстФичи = ТаблицаТекстФичи.Количество();
	
	
	
	Если СтруктураПараметров.ИдетЗагрузкаИзКаталога Тогда
		//ищем теги фильтр - начало
		
		
		НашлиТегИзФичиВСпискеТеговФильтр = Ложь;
		
		Для каждого СтрокаТаблицы Из ТаблицаТекстФичи Цикл
		    Стр = СтрокаТаблицы.Стр;
			
		
			//Стр = Текст.ПрочитатьСтроку();
			//Если Стр = Неопределено Тогда
			//	Прервать;
			//КонецЕсли;	
			
			Если Лев(Стр,1) = "@" Тогда //Это символ, обозначающий тег.
				Тег = СокрЛП(Сред(Стр,2));
				Если СтруктураПараметров.ИдетЗагрузкаИзКаталога Тогда //если явно указали одну фичу, то теги не должны мешать загрузке
					
					Зн = СписокТеговОтбор.НайтиПоЗначению(НРег(Тег));
					Если Зн <> Неопределено Тогда //значит эту фичу надо проигнорировать
						НашлиТегИзФичиВСпискеТеговФильтр = Истина;
					КонецЕсли;
				КонецЕсли;	 
				
				Продолжить;
			КонецЕсли;	 
			
		КонецЦикла;	
		//Текст.Закрыть();
		
		Если СписокТеговОтбор.Количество() > 0 Тогда
			Если Не НашлиТегИзФичиВСпискеТеговФильтр Тогда
				Сообщить("Не стал загружать фичу: " + ИмяФайла + ", т.к. в ней не найдено тегов фильтров.");
				СтруктураПараметров.Вставить("УдалитьСтрокуФичиИзДерева",Истина);
				Возврат Истина;
			КонецЕсли;	 
		КонецЕсли;	 
		
		//ищем теги фильтр - окончание
	КонецЕсли;	 
	
	
	
	
	НачалсяСценарий           = Ложь;
	НомСтр                    = 0;
	НомерСтрокиНачалоСценария = 0;
	ИмяОбласти                = "";
	Для СчетчикСтрокФичи = 1 По КолСтрокТаблицаТекстФичи Цикл
		СтрИсходная = ТаблицаТекстФичи[СчетчикСтрокФичи-1].Стр;
		
		НомСтр = ТаблицаТекстФичи[СчетчикСтрокФичи-1].НомСтр;
		
		Стр = СокрЛП(СтрИсходная);
		
		Если ПустаяСтрока(Стр) Тогда
			Продолжить;
		КонецЕсли;	 
		
		Если Лев(Стр,1) = "#" Тогда //Это комментарий. Его игнорируем.
			//но проверяем нет ли указания на язык описания фичи. 
			ПозицияПоиска = Найти(Стр, ТэгУказанияЯзыка);
			Если  ПозицияПоиска > 0 Тогда
				СтрокаЯзыка = СокрЛП(Сред(Стр, ПозицияПоиска+СтрДлина(ТэгУказанияЯзыка)));
				Если СоответствиеТаблицПереводов.Получить(СтрокаЯзыка) <> Неопределено Тогда 
					ТекущийЯзыкФичаФайла = СтрокаЯзыка;
				КонецЕсли;
			КонецЕсли;
			
			
			Если Лев(НРег(Стр),8) = "#область" Тогда
				ИмяОбласти = СокрЛП(Сред(Стр,9));
				СруктураОбласти = Новый Структура;
				СруктураОбласти.Вставить("ИмяОбласти",ИмяОбласти);
				СруктураОбласти.Вставить("НачалоОбласти",Истина);
				ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
			ИначеЕсли Лев(НРег(Стр),13) = "#конецобласти" Тогда
				СруктураОбласти = Новый Структура;
				СруктураОбласти.Вставить("ИмяОбласти","");
				СруктураОбласти.Вставить("НачалоОбласти",Ложь);
				ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
			КонецЕсли;	 
			
			
			Если НадоСтроитьДерево и НачалсяСценарий Тогда
				СтрТаблицаТекстФичи = ТаблицаТекстФичи[СчетчикСтрокФичи-1];
				Если СтрТаблицаТекстФичи.ЗначениеОтступа > СтрТаблицаТекстФичи.СледующийОступ Тогда
					//значит группа закрывается
					СруктураОбласти = Новый Структура;
					СруктураОбласти.Вставить("ИмяОбласти","");
					СруктураОбласти.Вставить("НачалоОбласти",Ложь);
					ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
					
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			
			Продолжить;
		КонецЕсли;	 
		
		Если Лев(Стр,1) = "@" Тогда //Это символ, обозначающий тег.
			Тег = СокрЛП(Сред(Стр,2));
			
			
			Если СтруктураПараметров.ИдетЗагрузкаИзКаталога Тогда //если явно указали одну фичу, то теги не должны мешать загрузке
				
				Зн = СписокТеговИсключение.НайтиПоЗначению(НРег(Тег));
				Если Зн <> Неопределено Тогда //значит эту фичу надо проигнорировать
					Сообщить("Не стал загружать фичу: " + ИмяФайла + ", т.к. обнаружен тег исключение: " + Тег);
					СтруктураПараметров.Вставить("УдалитьСтрокуФичиИзДерева",Истина);
					//Текст.Закрыть();
					Возврат Истина;
				КонецЕсли;
			КонецЕсли;	 
			
			
			Если НадоСтроитьДерево и НачалсяСценарий Тогда
				СтрТаблицаТекстФичи = ТаблицаТекстФичи[СчетчикСтрокФичи-1];
				Если СтрТаблицаТекстФичи.ЗначениеОтступа > СтрТаблицаТекстФичи.СледующийОступ Тогда
					//значит группа закрывается
					СруктураОбласти = Новый Структура;
					СруктураОбласти.Вставить("ИмяОбласти","");
					СруктураОбласти.Вставить("НачалоОбласти",Ложь);
					ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
					
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			Продолжить;
		КонецЕсли;	 
		
		
		Если Лев(Стр,1) = "|" Тогда
			Если (Не ИдетЧтениеПримеров) и (Не ИдетПередачаПараметровТаблицей) Тогда //значит ошибка в синтаксисе
				ОписаниеОшибки = "Строка №" + НомСтр + ", обнаружен символ ""|"", хотя не было ключевого слова ""Примеры"".";
				Возврат Ложь;
			КонецЕсли;	 
			
			СтрТаблицаСтрокиСРазделителями = Новый Структура;
			СтрТаблицаСтрокиСРазделителями.Вставить("Стр",Стр);
			Если ИдетЧтениеПримеров Тогда
				ТаблицаСтрокПримеров.Добавить(СтрТаблицаСтрокиСРазделителями);
			КонецЕсли;	 
			
			Если ИдетПередачаПараметровТаблицей Тогда
				ТаблицаСтрокПередачаПараметровТаблицей.Добавить(СтрТаблицаСтрокиСРазделителями);
			КонецЕсли;	 
			
			
			Если НадоСтроитьДерево и НачалсяСценарий Тогда
				СтрТаблицаТекстФичи = ТаблицаТекстФичи[СчетчикСтрокФичи-1];
				Если СтрТаблицаТекстФичи.ЗначениеОтступа > СтрТаблицаТекстФичи.СледующийОступ Тогда
					//значит группа закрывается
					СруктураОбласти = Новый Структура;
					СруктураОбласти.Вставить("ИмяОбласти","");
					СруктураОбласти.Вставить("НачалоОбласти",Ложь);
					ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
					
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			
			Продолжить;
		КонецЕсли;	 
		
		ПромСлово = "";
		ВтораяЧастьСтрокиПозиция = 1;
		ТекущееКлючевоеСлово = ПолучитьКлючевоеСлово(НРег(Стр), ВтораяЧастьСтрокиПозиция);
		ИмяШага = Стр;
		Если Лев(НРег(ИмяШага),9) = "сценарий:" Тогда
			ИмяШага = СокрЛП(Сред(ИмяШага,10));
		КонецЕсли;	 
		ВтораяЧастьСтроки = СокрЛП(Сред(Стр, ВтораяЧастьСтрокиПозиция));
		Символ = Лев(ВтораяЧастьСтроки, 1);
		Если (Символ=" ") или (Символ=":") или (Символ=",") Тогда
			ВтораяЧастьСтроки = Сред(ВтораяЧастьСтроки, 2);
		КонецЕсли;
	
		Если ТекущееКлючевоеСлово = "feature" Тогда
			ОписаниеФичи = ВтораяЧастьСтроки;
		ИначеЕсли (ТекущееКлючевоеСлово = "scenario") или (ТекущееКлючевоеСлово = "scenario_outline") Тогда
			НачалсяСценарий = Истина;
			Если ДеревоСтроки <> Неопределено Тогда
				ЗакрытьПредыдущийСценарий(ИмяФичи,ИмяФайла,ТекущийТипСценария,ПредыдущееКлючевоеСлово,ТекущееКлючевоеСлово,ДеревоСтроки,ОписаниеСценария,ТаблицаШагов,ТаблицаИзвестныхStepDefinition,ТаблицаСтрокПримеров,НомерСтрокиНачалоСценария,ТаблицаУжеСуществующихСценариев,СтруктураПараметров,МассивСценариевЗащитаОтЗацикливанияКеш);
			КонецЕсли;	 
			
			//Если МассивСценариевЗащитаОтЗацикливанияКеш <> Неопределено Тогда
			//	МассивСценариевЗащитаОтЗацикливанияКеш.Очистить();
			//КонецЕсли;	 
			
			НомерСтрокиНачалоСценария = НомСтр;
			ОписаниеСценария = СокрЛП(ВтораяЧастьСтроки);
			
			//Если (ТекущееКлючевоеСлово = "scenario") Тогда
			//	ТаблицаСценариев.Добавить(СоздатьСтруктуруДляСценария(ОписаниеСценария,ИмяФайла));
			//КонецЕсли;	 
		ИначеЕсли ТекущееКлючевоеСлово = "background" Тогда
			НомерСтрокиНачалоСценария = НомСтр;
			НачалсяСценарий = Истина;
		ИначеЕсли НадоСтроитьДерево и НачалсяСценарий Тогда
			СтрТаблицаТекстФичи = ТаблицаТекстФичи[СчетчикСтрокФичи-1];
			Если СтрТаблицаТекстФичи.ЗначениеОтступа < СтрТаблицаТекстФичи.СледующийОступ Тогда
				//значит группа открывается
				ИмяОбласти      = Стр;
				СруктураОбласти = Новый Структура;
				СруктураОбласти.Вставить("ИмяОбласти",ИмяОбласти);
				СруктураОбласти.Вставить("НачалоОбласти",Истина);
				ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
				
				Продолжить;
			КонецЕсли;	 
		Иначе
			СтрокаШага = ВтораяЧастьСтроки;
		КонецЕсли;	 
		
		Если ТекущееКлючевоеСлово = "" Тогда
			Если ПредыдущееКлючевоеСлово = "feature" Тогда
				//значит тут идёт описание фичи
				ОписаниеФичи = ОписаниеФичи + Символы.ПС + Стр;
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		Если Не ТекущееКлючевоеСловоСоответствуетОжидаемому(ТекущееКлючевоеСлово, ОжидаемоеКлючевоеСлово) Тогда
			Если ПредыдущееКлючевоеСлово = "feature" Тогда
				//значит тут идёт описание фичи
				Продолжить;
			КонецЕсли;	 
			
			СтрОшибки = ТекущееКлючевоеСлово;
			Если ТекущееКлючевоеСлово = "" Тогда
				СтрОшибки = ПромСлово;
				Если ПромСлово = "" Тогда
					СтрОшибки = Стр;
				КонецЕсли;	 
			КонецЕсли;	 
			ОписаниеОшибки = "Строка №" + НомСтр + ", ожидалось (" + ОжидаемоеКлючевоеСлово + "), а найдено (" + СтрОшибки + ") ПредыдущееКлючевоеСлово="+ПредыдущееКлючевоеСлово;
			Возврат Ложь;
		КонецЕсли;	 
		
		
		Если (ТекущееКлючевоеСлово = "given") или (ТекущееКлючевоеСлово = "when") или (ТекущееКлючевоеСлово = "then") или (ТекущееКлючевоеСлово = "and") или (ТекущееКлючевоеСлово = "but") Тогда
			ТаблицаСтрокПередачаПараметровТаблицей = СоздатьТаблицуСтрокПримеров();
			ДобавитьШаг(ТаблицаШагов,ВтораяЧастьСтроки,ИмяШага,НомСтр,ТаблицаСтрокПередачаПараметровТаблицей);
			
			ИдетПередачаПараметровТаблицей = Ложь;
			Если (Прав(СокрЛП(СтрИсходная),1) = ":") Тогда
				ИдетПередачаПараметровТаблицей = Истина;
			КонецЕсли;	 
		КонецЕсли;	 
		
		ПредыдущееКлючевоеСлово = ТекущееКлючевоеСлово;
		ОжидаемоеКлючевоеСлово  = ПолучитьСледующееОжидаемоеКлючевоеСлово(ТекущееКлючевоеСлово,ТекущийТипСценария,ИдетЧтениеПримеров);
		
		Если НадоСтроитьДерево и НачалсяСценарий Тогда
			СтрТаблицаТекстФичи = ТаблицаТекстФичи[СчетчикСтрокФичи-1];
			Если СтрТаблицаТекстФичи.ЗначениеОтступа > СтрТаблицаТекстФичи.СледующийОступ Тогда
				//значит группа закрывается
				СруктураОбласти = Новый Структура;
				СруктураОбласти.Вставить("ИмяОбласти","");
				СруктураОбласти.Вставить("НачалоОбласти",Ложь);
				ДобавитьШаг(ТаблицаШагов,"","","","",СруктураОбласти);
				
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		
	КонецЦикла;	
	
	
	Если ТаблицаШагов.Количество() > 0 Тогда
		ЗакрытьПредыдущийСценарий(ИмяФичи,ИмяФайла,ТекущийТипСценария,ПредыдущееКлючевоеСлово,"scenario",ДеревоСтроки,ОписаниеСценария,ТаблицаШагов,ТаблицаИзвестныхStepDefinition,ТаблицаСтрокПримеров,НомерСтрокиНачалоСценария,ТаблицаУжеСуществующихСценариев,СтруктураПараметров,МассивСценариевЗащитаОтЗацикливанияКеш);
	КонецЕсли;	 
	
	Возврат Истина;
	
КонецФункции

Функция БылиПовторыИменСнипетов(ТаблицаУжеСуществующихСценариев,ТаблицаИзвестныхStepDefinition)
	
	//Для каждого СтрТаблицаУжеСуществующихСценариев Из ТаблицаУжеСуществующихСценариев Цикл
	//	Сообщить("ИмяСценария1=" + СтрТаблицаУжеСуществующихСценариев.ИмяСценария);
	//КонецЦикла;
	
	
	КопияТаблицаУжеСуществующихСценариев = ТаблицаУжеСуществующихСценариев.Скопировать();
	Для каждого СтрТаблицаИзвестныхStepDefinition Из ТаблицаИзвестныхStepDefinition Цикл
		СтрКопияТаблицаУжеСуществующихСценариев             = КопияТаблицаУжеСуществующихСценариев.Добавить();
		СтрКопияТаблицаУжеСуществующихСценариев.ИмяСценария = СтрТаблицаИзвестныхStepDefinition.ID;
		
		//Сообщить("ИмяСценария2=" + СтрКопияТаблицаУжеСуществующихСценариев.ИмяСценария);
	КонецЦикла;
	
	БылоСтрок = КопияТаблицаУжеСуществующихСценариев.Количество();
	КопияТаблицаУжеСуществующихСценариев.Колонки.Добавить("Кол");
	Для каждого СтрКопияТаблицаУжеСуществующихСценариев Из КопияТаблицаУжеСуществующихСценариев Цикл
		СтрКопияТаблицаУжеСуществующихСценариев.Кол = 1;
	КонецЦикла;
	КопияТаблицаУжеСуществующихСценариев.Свернуть("ИмяСценария","Кол");
	
	СталоСтрок = КопияТаблицаУжеСуществующихСценариев.Количество();
	
	Если БылоСтрок <> СталоСтрок Тогда
		Для каждого СтрКопияТаблицаУжеСуществующихСценариев Из КопияТаблицаУжеСуществующихСценариев Цикл
			Если СтрКопияТаблицаУжеСуществующихСценариев.Кол <> 1 Тогда
				Сообщить("Снипет """ + СтрКопияТаблицаУжеСуществующихСценариев.ИмяСценария + """ встречается " + СтрКопияТаблицаУжеСуществующихСценариев.Кол + " раз!");
				
				Отбор = Новый Структура;
				Отбор.Вставить("ИмяСценария",СтрКопияТаблицаУжеСуществующихСценариев.ИмяСценария);
				МассивСтрокСценариев = ТаблицаУжеСуществующихСценариев.НайтиСтроки(Отбор);
				Для каждого СтрокаСценария Из МассивСтрокСценариев Цикл
					Сообщить("1. " + СтрокаСценария.ИмяФайла);
				КонецЦикла;
				
				
				
				Отбор = Новый Структура;
				Отбор.Вставить("ID",СтрКопияТаблицаУжеСуществующихСценариев.ИмяСценария);
				МассивСтрокStepDefinition = ТаблицаИзвестныхStepDefinition.НайтиСтроки(Отбор);
				Для каждого СтрокаСценария Из МассивСтрокStepDefinition Цикл
					Сообщить("2. " + СтрокаСценария.ИмяФайла);
				КонецЦикла;
				
				Сообщить(" ");
				
				
			КонецЕсли;	 
		КонецЦикла;
		Возврат Истина;
	КонецЕсли;	 
	
	
	
	Возврат Ложь;
КонецФункции	

Функция ЗагрузитьФичу(ИмяФайла,ДеревоСтроки,ТаблицаИзвестныхStepDefinition,СтруктураПараметров) Экспорт
	
	ЗаписьЖурналаРегистрации("ЗагрузитьФичу 1");
	
	Если НЕ СтруктураПараметров.Свойство("КешФич") Тогда
		КешФич = Новый ТаблицаЗначений;
		КешФич.Колонки.Добавить("ИмяФайла");
		КешФич.Колонки.Добавить("Дерево");
		
		СтруктураПараметров.Вставить("КешФич",КешФич);
	КонецЕсли;	 
	
	ЗаписьЖурналаРегистрации("ЗагрузитьФичу 2");
	
	
	ДобавитьКолонкуСнипетаВТаблицаУжеСуществующихСценариев(СтруктураПараметров.ТаблицаУжеСуществующихСценариев);
	
	
	Если НЕ СтруктураПараметров.Свойство("БылаПроверкаНаПовторыСнипетов") Тогда
		Если БылиПовторыИменСнипетов(СтруктураПараметров.ТаблицаУжеСуществующихСценариев,ТаблицаИзвестныхStepDefinition) Тогда
			ВызватьИсключение "Были конфликты в именах снипетов!";
		КонецЕсли;
		СтруктураПараметров.Вставить("БылаПроверкаНаПовторыСнипетов",Истина);
	КонецЕсли;	
	
	
	
	ОписаниеОшибки = "";
	Если Не ПроверитьФичуНаКорректностьСинтаксисаИЗагрузитьСценарии(ИмяФайла,ОписаниеОшибки,ДеревоСтроки,ТаблицаИзвестныхStepDefinition,СтруктураПараметров) Тогда
		Сообщить("Не смог загрузить " + ИмяФайла + ". " + ОписаниеОшибки);
		СтруктураПараметров.Вставить("ФичаЗагружена",Ложь);
		СтруктураПараметров.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		Возврат Неопределено;
	КонецЕсли;	 
	
	СтруктураПараметров.Вставить("ФичаЗагружена",Истина);
	
КонецФункции

Функция ОбходКаталогов (ПутьКаталога,врДерево,ТаблицаИзвестныхStepDefinition,СтруктураПараметров)
	ФайлПутьКаталога = Новый Файл(ПутьКаталога);
	Если ФайлПутьКаталога.ЭтоКаталог() Тогда
		НайденныеФайлы = НайтиФайлы(ПутьКаталога,"*");
	Иначе
		НайденныеФайлы = Новый Массив;//вернём одну фичу
		НайденныеФайлы.Добавить(ФайлПутьКаталога);
	КонецЕсли;	 
	Для каждого ф из НайденныеФайлы цикл
		Если ф.ЭтоКаталог() тогда
			НовСтр = врДерево.Строки.Добавить();
			НовСтр.Каталог    = Истина;
			НовСтр.ПолныйПуть = ф.ПолноеИмя;
			НовСтр.Имя        = ф.Имя;
			ОбходКаталогов(ПутьКаталога+"\"+ф.Имя,НовСтр,ТаблицаИзвестныхStepDefinition,СтруктураПараметров);
			
			Если НовСтр.Строки.Количество() = 0 Тогда
				врДерево.Строки.Удалить(НовСтр);
			КонецЕсли;
		ИначеЕсли НРег(ф.Расширение) = ".feature" Тогда
			НовСтр            = врДерево.Строки.Добавить();
			НовСтр.Фича       = Истина;
			
			НовСтр.ПолныйПуть = ф.ПолноеИмя;
			НовСтр.Имя        = ф.ИмяБезРасширения;
			
			СтруктураПараметров.Вставить("УдалитьСтрокуФичиИзДерева",Ложь);
			
			ЗагрузитьФичу(ф.ПолноеИмя,НовСтр.Строки,ТаблицаИзвестныхStepDefinition,СтруктураПараметров);
			
			Если СтруктураПараметров.УдалитьСтрокуФичиИзДерева Тогда
				врДерево.Строки.Удалить(НовСтр);
			КонецЕсли;	 
		КонецЕсли;
	КонецЦикла;
КонецФункции

Процедура ЗаполнитьДерево(ДеревоЗначений,Каталог,ТаблицаИзвестныхStepDefinition,СтруктураПараметров)
	Файл = Новый Файл(Каталог);
	
	НовСтр            = ДеревоЗначений.Строки.Добавить();
	НовСтр.Каталог    = Истина;
	НовСтр.Имя        = Файл.Имя;
	НовСтр.ПолныйПуть = Каталог;
	ОбходКаталогов(Каталог,НовСтр,ТаблицаИзвестныхStepDefinition,СтруктураПараметров);    
КонецПроцедуры

Процедура ОбработатьКаталогФич(ДеревоЗначений,ПутьКФичам,ТаблицаИзвестныхStepDefinition,СтруктураПараметров)
	//Заполним дерево файлами фич с учетом иерархии
	ЗаполнитьДерево(ДеревоЗначений,ПутьКФичам,ТаблицаИзвестныхStepDefinition,СтруктураПараметров);
КонецПроцедуры

Функция СоздатьДеревоЗначений()
	ДеревоЗначений = Новый ДеревоЗначений;
	ДеревоЗначений.Колонки.Добавить("Имя");
	ДеревоЗначений.Колонки.Добавить("ПолныйПуть");
	ДеревоЗначений.Колонки.Добавить("Каталог");
	ДеревоЗначений.Колонки.Добавить("Фича");
	ДеревоЗначений.Колонки.Добавить("Сценарий");
	ДеревоЗначений.Колонки.Добавить("ЭтоScenarioOutline");
	ДеревоЗначений.Колонки.Добавить("ЭтоКонтекст");
	ДеревоЗначений.Колонки.Добавить("Примеры");
	ДеревоЗначений.Колонки.Добавить("ИменованныеПараметры");
	ДеревоЗначений.Колонки.Добавить("Пример");
	ДеревоЗначений.Колонки.Добавить("Шаг");
	ДеревоЗначений.Колонки.Добавить("ЗначенияПараметров");
	ДеревоЗначений.Колонки.Добавить("Снипет");
	ДеревоЗначений.Колонки.Добавить("АдресСнипета");
	ДеревоЗначений.Колонки.Добавить("ЭтоЧужойСнипет");
	ДеревоЗначений.Колонки.Добавить("СтрокаРеальнойПроцедуры");
	ДеревоЗначений.Колонки.Добавить("ТипКартинки");
	ДеревоЗначений.Колонки.Добавить("ШагСПараметрамиВТаблице");
	ДеревоЗначений.Колонки.Добавить("СтрокаПараметровШагаВВидеТаблицы");
	ДеревоЗначений.Колонки.Добавить("ПараметрыТаблицы");
	ДеревоЗначений.Колонки.Добавить("ИмяШагаБезКлючевогоСлова");
	ДеревоЗначений.Колонки.Добавить("ШагСценарий");
	ДеревоЗначений.Колонки.Добавить("МассивСценариевЗащитаОтЗацикливания");
	ДеревоЗначений.Колонки.Добавить("Область");
	
	Возврат ДеревоЗначений;
КонецФункции	

Функция ПолучитьДеревоФич(СтруктураПараметров) Экспорт
	КаталогИнструментов     = СтруктураПараметров.КаталогИнструментов;
	КаталогФич              = СтруктураПараметров.КаталогФич;
	МассивСообщений         = СтруктураПараметров.МассивСообщений;
	DebugLog                = СтруктураПараметров.DebugLog;
	КонтекстVanessaBehavoir = СтруктураПараметров.КонтекстVanessaBehavoir;
	КаталогиБиблиотек       = СтруктураПараметров.КаталогиБиблиотек;
	СписокТеговИсключение   = СтруктураПараметров.СписокТеговИсключение;
	СписокТеговОтбор        = СтруктураПараметров.СписокТеговОтбор;
	
	
	ПутьКФичам = Новый Файл(КаталогФич);
	Если Не ПутьКФичам.Существует() Тогда
		МассивСообщений.Добавить("Не найден путь " + КаталогФич);
		Возврат Неопределено;
	КонецЕсли;	 
	
	
	
	
	ТаблицаКонтекстовОбработок = Новый Массив;
	
	
	ТаблицаИзвестныхStepDefinition = СтруктураПараметров.ТаблицаИзвестныхStepDefinition;
	ТаблицаВерсийEPF               = СтруктураПараметров.ТаблицаВерсийEPF;
	
	
	Путь = ПутьКФичам.ПолноеИмя;
	СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Истина);
	Если ПутьКФичам.ЭтоФайл() Тогда
		СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Ложь);
		Путь = ПутьКФичам.Путь;
	КонецЕсли;	 
	
	
	
	ПолучитьУжеСуществующиеСнипетыИзОбработок(Путь,ТаблицаКонтекстовОбработок,ТаблицаИзвестныхStepDefinition,ТаблицаВерсийEPF,КонтекстVanessaBehavoir);
	Для каждого Элем Из КаталогиБиблиотек Цикл
		ПолучитьУжеСуществующиеСнипетыИзОбработок(Элем.Значение,ТаблицаКонтекстовОбработок,ТаблицаИзвестныхStepDefinition,ТаблицаВерсийEPF,КонтекстVanessaBehavoir);
	КонецЦикла;
	
	
	
	
	ДеревоЗначений = СоздатьДеревоЗначений();
	
	
	//Если ПутьКФичам.ЭтоКаталог() Тогда
	ОбработатьКаталогФич(ДеревоЗначений,ПутьКФичам.ПолноеИмя,ТаблицаИзвестныхStepDefinition,СтруктураПараметров);
	//ДеревоЗначений.ВыбратьСтроку();
	//КонецЕсли;	 
	
	
	
	
	
	
	
	Возврат ДеревоЗначений;
КонецФункции

Процедура ДобавитьКлючевоеСловоВТаблицу(Тзн,Слово,Тип)
	СтруктураКлючевогоСлова = Новый Структура;
	СтруктураКлючевогоСлова.Вставить("Слово",Слово);
	СтруктураКлючевогоСлова.Вставить("Тип",Тип);
	
	Тзн.Добавить(СтруктураКлючевогоСлова);
	
КонецПроцедуры

Процедура СоздатьEPFПоМассивуФич(СтруктураПараметров) Экспорт
	СделатьСообщение("Запускаю генерацию epf.");
	ГенерироватьУФ      = СтруктураПараметров.ГенерироватьУФ;
	DebugLog            = СтруктураПараметров.DebugLog;
	КаталогИнструментов = СтруктураПараметров.КаталогИнструментов;
	ШагСтрокДляМодуля   = СтруктураПараметров.ШагСтрокДляМодуля;
	СделатьGenerateEpf(СтруктураПараметров);
	
КонецПроцедуры

Функция СоздатьПустуюСтруктуруEpf() Экспорт
	Стр = Новый Структура;
	Стр.Вставить("ИмяФичи","");
	Стр.Вставить("ИмяФайлаEpf","");
	Стр.Вставить("ВременноеИмяМодуля","");
	Стр.Вставить("ТелоМодуля","");//таблица значений
	Стр.Вставить("ИмяМодуляEpf","");
	Стр.Вставить("КаталогИсходников","");
	Стр.Вставить("ФайлEpfПересоздавался",Ложь);
	
	Возврат Стр;
КонецФункции

Процедура ЗаписатьФайлВерсииИсходников(ИмяФайлаВерсииИсходников,ИмяФайлаОригинала)
	Возврат;
	
	
	ФайлВерсии = Новый Файл(ИмяФайлаВерсииИсходников);
	Если ФайлВерсии.Существует() Тогда
		УдалитьФайлы(ФайлВерсии.ПолноеИмя);
	КонецЕсли;	 
	
	Файл   = Новый Файл(ИмяФайлаОригинала);
	Версия = Строка(Файл.ПолучитьВремяИзменения());
	
	ЗТ = Новый ЗаписьТекста(ИмяФайлаВерсииИсходников,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку("Версия="+Версия); 
	
	ЗТ.Закрыть();
КонецПроцедуры

Функция ПолучитьВерсиюИсходников(ИмяФайлаВерсииИсходников)
	ФайлВерсии = Новый Файл(ИмяФайлаВерсииИсходников);
	Если Не ФайлВерсии.Существует() Тогда
		Возврат Неопределено;
	КонецЕсли;	 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаВерсииИсходников,"UTF-8");
	
	СтрокаВозврата = Неопределено;
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Поз = Найти(Стр,"=");
		Если Поз > 0 Тогда
			СтрокаВозврата = Сред(Стр,Поз+1);
		КонецЕсли;	 
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат СтрокаВозврата;
	
КонецФункции

Функция РаспаковатьEPF(СтруктураОписанияEpf)
    ИмяФайла = СтруктураОписанияEpf.ИмяФайлаEPF;

	Попытка
		
		Файл = Новый Файл(ИмяФайла);
		
        ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
        КопироватьФайл(ИмяФайла,ВременноеИмяФайла);
        
        ВременныйФайл = Новый Файл(ВременноеИмяФайла);
		
		
        ИмяКаталогаДляИсходников = ВременныйФайл.Путь + "Src";
        ИмяФайлаВерсииИсходников = ВременныйФайл.Путь + "Src" + ВременныйФайл.ИмяБезРасширения + "SrcVersion.vb";
		
		Если ГенерироватьУФ Тогда
			ПутьКФайлуМодуля = ИмяКаталогаДляИсходников + "\" + ВременныйФайл.ИмяБезРасширения + "\Form\Форма\Форма.txt";
		Иначе	
			ПутьКФайлуМодуля = ИмяКаталогаДляИсходников + "\" + ВременныйФайл.ИмяБезРасширения + "\ObjectModule.txt";
		КонецЕсли;	 
		
		
		//ВерсияИсходников = ПолучитьВерсиюИсходников(ИмяФайлаВерсииИсходников);
		//Если ВерсияИсходников = Строка(Файл.ПолучитьВремяИзменения()) Тогда
		//	Отладка("Не стал распаковывать " + ИмяФайла + ", т.к. совпали версия файла и исходников. " + ВерсияИсходников);
		//	Возврат ПутьКФайлуМодуля;
		//КонецЕсли;	 
		//СделатьСообщение("Надо распаковывать " + ИмяФайла + ", т.к. не совпали версия файла и исходников.");
		
		
		УдалитьФайлы(ИмяКаталогаДляИсходников + "\" + ВременныйФайл.ИмяБезРасширения);
		ФайлКаталогSrc = Новый Файл(ИмяКаталогаДляИсходников);
		Если Не ФайлКаталогSrc.Существует() Тогда
			СоздатьКаталог(ИмяКаталогаДляИсходников);
		КонецЕсли;	 
		
		СтрокаРазборкиEpf = "python " + КаталогИнструментов + "\vendor\precommit1c\pyv8unpack.py  """ +  ВременноеИмяФайла + """ """ + ИмяКаталогаДляИсходников + """";
		СделатьСообщение("Делаю распаковку " + Файл.ПолноеИмя);
		Отладка("Строка распаковки: " + СтрокаРазборкиEpf);
		
		#Если Клиент Тогда
		КомандаСистемы(СтрокаРазборкиEpf,КаталогИнструментов);
		#КонецЕсли
		//ВыполнитьКомандуОС(СтрокаРазборкиEpf);
		
		
		Файл = Новый Файл(ПутьКФайлуМодуля);
		Если Не Файл.Существует() Тогда
			СделатьСообщение("Не найден файл после распаковки: " + ПутьКФайлуМодуля);
			Если ЭтоУФ Тогда
				СделатьСообщение("Возможно это обработка для обычных форм, а не для управляемых форм.");
			Иначе	
				СделатьСообщение("Возможно это обработка для управляемых форм, а не для обычных форм.");
			КонецЕсли;	 
			Возврат Неопределено;
		КонецЕсли;	 
		
        СтруктураОписанияEpf.КаталогИсходников = ИмяКаталогаДляИсходников + "\" + ВременныйФайл.ИмяБезРасширения;
		ЗаписатьФайлВерсииИсходников(ИмяФайлаВерсииИсходников,ИмяФайла);
		
		Возврат ПутьКФайлуМодуля;
	Исключение
		СделатьСообщение("Не смог распаковать " + ИмяФайла);
		СделатьСообщение(ОписаниеОшибки());
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

Функция ЗагрузитьТелоМодуляВТаблицуЗначений(ПутьКФайлу)
	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("НомСтр");
	Тзн.Колонки.Добавить("Стр");
	
	НомСтр = 0;
	
	
	ПромФайл = Новый Файл(ПутьКФайлу);
	Если Не ПромФайл.Существует() Тогда
		СтрОшибки = "Файл """ + ПутьКФайлу + """ не существует!";
		Сообщить(СтрОшибки);
		ВызватьИсключение СтрОшибки;
	КонецЕсли; 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ПутьКФайлу,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		НомСтр = НомСтр + ШагСтрокДляМодуля;
		
		СтрТзн        = Тзн.Добавить();
		СтрТзн.НомСтр = НомСтр;
		СтрТзн.Стр    = Стр;
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат Тзн;
КонецФункции

Функция СоздатьСтруктураОписанияEpf(ОтносительныйКаталогФичи,ИмяТекущейФичи,GenerateEpf,СоздаватьОбластиПриГенерацииКода)
	СтруктураОписанияEpf                    = СоздатьПустуюСтруктуруEpf();
	СтруктураОписанияEpf.ИмяФичи            = ИмяТекущейФичи;
	СтруктураОписанияEpf.ИмяФайлаEpf        = ОтносительныйКаталогФичи + "\step_definitions\" + ИмяТекущейФичи + ".epf";
	
	//СтруктураОписанияEpf.ИмяМодуляEpf       = КаталогИнструментов + "\src" + ОтносительныйКаталогФичи + "\step_definitions\" + ИмяТекущейФичи + "\ObjectModule.txt";
	Если GenerateEpf Тогда
		ФайлEpf = Новый Файл(СтруктураОписанияEpf.ИмяФайлаEpf);
		Если ФайлEpf.Существует() Тогда //т.е. если мы не первый раз работаем с данной фичей
			//Если ЭтоФайлДляОбычныхФорм(СтруктураОписанияEpf.ИмяФайлаEpf) Тогда
			//КонецЕсли;	 
			
			СтруктураОписанияEpf.ИмяМодуляEpf          = РаспаковатьEPF(СтруктураОписанияEpf);
			СтруктураОписанияEpf.ФайлEpfПересоздавался = Истина;
		КонецЕсли;	 
	КонецЕсли;
	
	Если Не СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
		СтруктураОписанияEpf.КаталогИсходников = КаталогИнструментов + "\lib\TemplateEpf";
		Если ГенерироватьУФ Тогда
			СтруктураОписанияEpf.КаталогИсходников = КаталогИнструментов + "\lib\TemplateEpfUF";
		КонецЕсли;	   
	КонецЕсли;	   
	
	//если уже были исходники, то надо использовать их
	//ПромИмяФайла = ОтносительныйКаталогФичи + "\step_definitions\src\" + ИмяТекущейФичи;
	//ПромИсходникиФайл = Новый Файл(ПромИмяФайла);
	
	
	СтруктураОписанияEpf.ВременноеИмяМодуля = СтруктураОписанияEpf.КаталогИсходников + "\ObjectModule_" + ИмяТекущейФичи + ".txt";
	Если ГенерироватьУФ Тогда
		СтруктураОписанияEpf.ВременноеИмяМодуля = СтруктураОписанияEpf.КаталогИсходников + "\und\70e297e0-e8a2-43bf-8be1-62e408f610a1.0_" + ИмяТекущейФичи + ".txt";
	КонецЕсли;	 
	
	//ПромИмяФайла = ОтносительныйКаталогФичи + "\step_definitions\src\" + ИмяТекущейФичи + "\ObjectModule_" + ИмяТекущейФичи + ".txt";
	
	//Сообщить("СтруктураОписанияEpf.ИмяМодуляEpf="+СтруктураОписанияEpf.ИмяМодуляEpf);
	
	
	УдалитьФайлы(СтруктураОписанияEpf.ВременноеИмяМодуля);
	
	
	Файл = Новый Файл(СтруктураОписанияEpf.ВременноеИмяМодуля);
	Если Не Файл.Существует() Тогда
		//Сообщить(СтруктураОписанияEpf.ВременноеИмяМодуля);
		ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Истина); 
		ЗТ.Закрыть();
	КонецЕсли;
	
	
	Файл = Новый Файл(СтруктураОписанияEpf.ИмяМодуляEpf); //значит надо загрузить модуль из исходников
	Если Файл.Существует() Тогда
		СтруктураОписанияEpf.ТелоМодуля = ЗагрузитьТелоМодуляВТаблицуЗначений(СтруктураОписанияEpf.ИмяМодуляEpf);
	Иначе
		СтруктураОписанияEpf.ТелоМодуля = ЗагрузитьТелоМодуляВТаблицуЗначений(СтруктураОписанияEpf.ВременноеИмяМодуля);
		//значит создаём файл первый разделим
		ДобавитьНачальноеЗаполнениеВМодуль(СтруктураОписанияEpf.ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,,СоздаватьОбластиПриГенерацииКода);
	КонецЕсли;
	
	
	
	
	//МассивДляСозданияEpf.Добавить(СтруктураОписанияEpf);
	//Отладка("Добавляю фичу " + СтруктураОписанияEpf.ИмяФичи + " в МассивДляСозданияEpf.");
	
	
	Возврат СтруктураОписанияEpf;
КонецФункции

Процедура ДобавитьНачальноеЗаполнениеВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,ЭтоУФ = Ложь,СоздаватьОбластиПриГенерацииКода) Экспорт
	
	Если ЭтоУФ Тогда
		ТелоМодуля = ЗначениеИзСтрокиВнутр(ТелоМодуля);
	КонецЕсли;	 
	
	//ДобавитьСтрокуВМодуль(ТелоМодуля,"Перем Контекст Экспорт;");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если СоздаватьОбластиПриГенерацииКода Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"#Область Служебные_функции_и_процедуры");
	Иначе	
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"//Служебные функции и процедуры");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// контекст фреймворка Vanessa-Behavior");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Перем Ванесса;");
	
	
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля," ");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Структура, в которой хранится состояние сценария между выполнением шагов. Очищается перед выполнением каждого сценария.");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Перем Контекст Экспорт;");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля," ");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Структура, в которой можно хранить служебные данные между запусками сценариев. Существует, пока открыта форма Vanessa-Behavior.");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Перем КонтекстСохраняемый Экспорт;");
	КонецЕсли;	 
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Служебная функция.");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Функция ДобавитьШагВМассивТестов(МассивТестов,Снипет,ИмяПроцедуры,ПредставлениеТеста = Неопределено,Транзакция = Неопределено,Параметр = Неопределено)");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура = Новый Структура;");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""Снипет"",Снипет);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""ИмяПроцедуры"",ИмяПроцедуры);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""ИмяПроцедуры"",ИмяПроцедуры);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""ПредставлениеТеста"",ПредставлениеТеста);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""Транзакция"",Транзакция);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Структура.Вставить(""Параметр"",Параметр);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	МассивТестов.Добавить(Структура);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецФункции");
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Функция экспортирует список шагов, которые реализованы в данной внешней обработке.");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Функция ПолучитьСписокТестов(КонтекстФреймворкаBDD) Экспорт");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Ванесса = КонтекстФреймворкаBDD;");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	ВсеТесты = Новый Массив;");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Возврат ВсеТесты;");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецФункции");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	");
	
	
	
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаСервере");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Служебная функция.");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Функция ПолучитьМакетСервер(ИмяМакета)");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	ОбъектСервер = РеквизитФормыВЗначение(""Объект"");");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Возврат ОбъектСервер.ПолучитьМакет(ИмяМакета);");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецФункции");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Служебная функция для подключения библиотеки создания fixtures.");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Функция ПолучитьМакетОбработки(ИмяМакета) Экспорт");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Возврат ПолучитьМакетСервер(ИмяМакета);");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецФункции");
	Иначе	
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Служебная функция для подключения библиотеки создания fixtures.");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Функция ПолучитьМакетОбработки(ИмяМакета) Экспорт");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Возврат ПолучитьМакет(ИмяМакета);");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецФункции");
	КонецЕсли;	 
	
	
	
	Если СоздаватьОбластиПриГенерацииКода Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"#КонецОбласти");
	КонецЕсли;	 
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если СоздаватьОбластиПриГенерацииКода Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"#Область Работа_со_сценариями");
	Иначе	
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"//Работа со сценариями");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
	КонецЕсли;	 
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Процедура выполняется перед началом каждого сценария");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Процедура ПередНачаломСценария() Экспорт");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецПроцедуры");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	
	
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"// Процедура выполняется перед окончанием каждого сценария");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"Процедура ПередОкончаниемСценария() Экспорт");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"КонецПроцедуры");
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	
	Если СоздаватьОбластиПриГенерацииКода Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"#КонецОбласти");
	КонецЕсли;	 
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	
	
	//Если СоздаватьОбластиПриГенерацииКода Тогда
	//	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"#Область Реализация_шагов");
	//Иначе	
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"//Реализация шагов");
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"///////////////////////////////////////////////////");
	//КонецЕсли;	 
	
	Если ЭтоУФ Тогда
		ТелоМодуля = ЗначениеВСтрокуВнутр(ТелоМодуля);
	КонецЕсли;	 
КонецПроцедуры

Функция ПолучитьМаксНомерИзТелаМодуля(ТелоМодуля)
	Если ТелоМодуля.Количество() = 0 Тогда
		Возврат 0;
	КонецЕсли;
	
	Возврат ТелоМодуля[ТелоМодуля.Количество()-1].НомСтр;
КонецФункции

Процедура ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,Стр,НомерСрокиМодуля = Неопределено)
	НомСтр = ПолучитьМаксНомерИзТелаМодуля(ТелоМодуля);
	
	
	СтрТелоМодуля = ТелоМодуля.Добавить();
	Если НомерСрокиМодуля = Неопределено Тогда
		СтрТелоМодуля.НомСтр = НомСтр + ШагСтрокДляМодуля;
	Иначе
		СтрТелоМодуля.НомСтр = НомерСрокиМодуля;
	КонецЕсли;	 
	СтрТелоМодуля.Стр    = Стр;
	
	
	//Сообщить("ТелоМодуля.Количество()=" + ТелоМодуля.Количество());
КонецПроцедуры

Функция ПолучитьТелоМодуляВМассивСервер(Стр)
КонецФункции

Функция УбратьСпецсимволыИзИмениОбработи(Знач Стр)
	Стр = СтрЗаменить(Стр," ","_");
	Стр = СтрЗаменить(Стр,"`","");
	Стр = СтрЗаменить(Стр,"~","");
	Стр = СтрЗаменить(Стр,"'","");
	Стр = СтрЗаменить(Стр,".","");
	Стр = СтрЗаменить(Стр,",","");
	Стр = СтрЗаменить(Стр,":","");
	Стр = СтрЗаменить(Стр,";","");
	Стр = СтрЗаменить(Стр,"-","_");  
	Стр = СтрЗаменить(Стр,"+","");
	Стр = СтрЗаменить(Стр,"/","");
	Стр = СтрЗаменить(Стр,"\","");
	Стр = СтрЗаменить(Стр,"=","");
	Стр = СтрЗаменить(Стр,"!","");
	Стр = СтрЗаменить(Стр,"@","");
	Стр = СтрЗаменить(Стр,"#","");
	Стр = СтрЗаменить(Стр,"$","");
	Стр = СтрЗаменить(Стр,"%","");
	Стр = СтрЗаменить(Стр,"^","");
	Стр = СтрЗаменить(Стр,"&","");
	Стр = СтрЗаменить(Стр,"*","");
	Стр = СтрЗаменить(Стр,"(","");
	Стр = СтрЗаменить(Стр,")","");
	Стр = СтрЗаменить(Стр,"№","");
	Стр = СтрЗаменить(Стр,"?","");
	Стр = СтрЗаменить(Стр,"<","");
	Стр = СтрЗаменить(Стр,">","");
	
	Возврат Стр;
КонецФункции	

Процедура ЗаменитьСтрокиВФайлеОсновыОбработки(ИмяФайлОсноваОбработки,ИмяФичи)
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлОсноваОбработки,"UTF-8");
	
	
	ВременноеИмяФайла = ИмяФайлОсноваОбработки + "_Temp";
	ЗТ = Новый ЗаписьТекста(ВременноеИмяФайла,"UTF-8",,Истина); 
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		ИмяОбработки = УбратьСпецсимволыИзИмениОбработи(ИмяФичи);
		Стр = СтрЗаменить(Стр,"TemplateEpf",ИмяОбработки);
		Стр = СтрЗаменить(Стр,"Template epf",ИмяФичи);
		
		ЗТ.ЗаписатьСтроку(Стр); 
	КонецЦикла;
	
	ЗТ.Закрыть();
	Текст.Закрыть();
	Текст = "";
	//Приостановить(500);
	
	
	УдалитьФайлы(ИмяФайлОсноваОбработки);
	ПереместитьФайл(ВременноеИмяФайла,ИмяФайлОсноваОбработки);
	
КонецПроцедуры

Процедура СоздатьКаталогЕслиЕгоНет(Путь)
	Файл = Новый Файл(Путь);
	Если Путь = "" Тогда
		ВызватьИсключение "Передан пустой путь в процедуру ""СоздатьКаталогЕслиЕгоНет""!";
	КонецЕсли;	 
	Если Не Файл.Существует() Тогда
		СоздатьКаталог(Путь);
		Отладка("Создан каталог: " + Путь);
	КонецЕсли;
КонецПроцедуры

Процедура УдалитьИзФайлаМодуляФормыУФТестМодуляФормы(ИмяФайлаФормаУФ)
	Файл = Новый Файл(ИмяФайлаФормаУФ);
	
	Если Не Файл.Существует() Тогда
		ВызватьИсключение "УдалитьИзФайлаМодуляФормыУФТестМодуляФормы. Файл " + ИмяФайлаФормаУФ + " не найден!";
	КонецЕсли;	 
	
	
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("txt");
	//Сообщить("ВременноеИмяФайла=" + ВременноеИмяФайла);
	
	ЗТ = Новый ЗаписьТекста(ВременноеИмяФайла,"UTF-8",,Истина); 
	
	
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаФормаУФ,"UTF-8");
	
	
	НачалоМодуля = -1;
	КонецМодуля  = -1;
	
	НашлиМодуль = Ложь;
	
	КолСкобок1  = 0;
	КолСкобок2  = 0;
	НомерСтроки = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		НомерСтроки = НомерСтроки + 1;
		
		КолСкобок1 = КолСкобок1 + СтрЧислоВхождений(Стр,"{");
		КолСкобок2 = КолСкобок2 + СтрЧислоВхождений(Стр,"}");
		
		//Сообщить("Строка №" + НомерСтроки + ", " + КолСкобок1 + ", " + КолСкобок2 + ": " + Стр);
		
		//Если НомерСтроки = 303 Тогда
		//	ыва = 1;
		//КонецЕсли;	 
		
		
		
		
		
		Если (НачалоМодуля > 0) И НЕ НашлиМодуль Тогда
			Если Лев(Стр,1) = "{" Тогда
				КонецМодуля = НомерСтроки;
				ЗТ.ЗаписатьСтроку(""","); 
				ЗТ.ЗаписатьСтроку(Стр); 
				НашлиМодуль = Истина;
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		Если (НомерСтроки > 2) И (НачалоМодуля = -1) И НЕ НашлиМодуль Тогда
			//Если (КолСкобок1 - КолСкобок2) = 1 Тогда //значит сейчас начинается модуль
			Поз = Найти(Стр,"},""");
			Если (Поз > 0) И (Прав(Стр,1) <> ",") Тогда
				НачалоМодуля = НомерСтроки;
				
				НачалоСтроки = Лев(Стр,Поз-1);
				
				ЗТ.ЗаписатьСтроку(НачалоСтроки + "},""//начало текста модуля"); 
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		
		Если (НачалоМодуля > 0) и НЕ НашлиМодуль Тогда
			Продолжить;
		КонецЕсли;	 
		
		ЗТ.ЗаписатьСтроку(Стр); 
		
	КонецЦикла;	
	
	Текст.Закрыть();
	ЗТ.Закрыть();
	
	
	Если Не НашлиМодуль Тогда
		ВызватьИсключение "Не смог найти код модуля формы в файле ИмяФайлаФормаУФ!";
	КонецЕсли;	 
	
	
	Отладка("Копирю файл " + ВременноеИмяФайла + " в " + ИмяФайлаФормаУФ);
	КопироватьФайл(ВременноеИмяФайла,ИмяФайлаФормаУФ);
	
КонецПроцедуры

Процедура СоздатьФайлыОбработок(БылиОшибки,СтруктураОписанияEpf)
	
	ТелоМодуля = СтруктураОписанияEpf.ТелоМодуля;
	Если ЭтоУФ Тогда
		ТелоМодуля = ПолучитьТелоМодуляВМассивСервер(ТелоМодуля);
	Иначе
		ТелоМодуля.Сортировать("НомСтр");
		ТелоМодуля = ТелоМодуля.ВыгрузитьКолонку("Стр");
	КонецЕсли;	 
	
	
	
	Отладка("Буду записывать " + СтруктураОписанияEpf.ВременноеИмяМодуля);
	
	УдалитьФайлы(СтруктураОписанияEpf.ВременноеИмяМодуля);
	Если ГенерироватьУФ Тогда
		ИмяФайлаФормаУФ = КаталогИнструментов + "\lib\TemplateEpfUF\und\70e297e0-e8a2-43bf-8be1-62e408f610a1.0_template";
		Если СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
			ИмяФайлаФормаУФ = СтруктураОписанияEpf.КаталогИсходников + "\und\70e297e0-e8a2-43bf-8be1-62e408f610a1.0";
			
			УдалитьИзФайлаМодуляФормыУФТестМодуляФормы(ИмяФайлаФормаУФ);
			
			ФайлИмяФайлаФормаУФ = Новый Файл(ИмяФайлаФормаУФ);
			Если Не ФайлИмяФайлаФормаУФ.Существует() Тогда
				ВызватьИсключение "Ошибка перегенерации EPF. Файл " + ИмяФайлаФормаУФ + " не найден.";
			КонецЕсли;	 
		КонецЕсли;	 
		//ИмяФайлаФормаУФ = СтруктураОписанияEpf.ВременноеИмяМодуля;
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяФайлаФормаУФ,"UTF-8");
		
		ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Истина); 
		
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			ЗТ.ЗаписатьСтроку(Стр); 
			
			Если Найти(Стр,"},""//начало текста модуля") > 0 Тогда
				Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
					Если СтрТелоМодуля = "//начало текста модуля" Тогда
						Продолжить;
					КонецЕсли;	 
					
					//СделатьСообщение("СтрТелоМодуля.Стр = " + СтрТелоМодуля.Стр);
					СтрТелоМодуля = СтрЗаменить(СтрТелоМодуля,"""","""""");
					ЗТ.ЗаписатьСтроку(СтрТелоМодуля); 
					//ЗТ.Записать(Символы.ПС); 
				КонецЦикла;
			КонецЕсли;	 
		КонецЦикла;	
		
		
		Текст.Закрыть();
		ЗТ.Закрыть();
	Иначе	
		ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Истина); 
		Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
			//СделатьСообщение("СтрТелоМодуля.Стр = " + СтрТелоМодуля.Стр);
			ЗТ.ЗаписатьСтроку(СтрТелоМодуля); 
			//ЗТ.Записать(Символы.ПС); 
		КонецЦикла;
		ЗТ.Закрыть();
	КонецЕсли;	 
	Отладка("Записал " + СтруктураОписанияEpf.ВременноеИмяМодуля);
	
	
	//ПутьКИсходникам = КаталогИнструментов + "\lib\TemplateEpf\";
	//ИмяФайлаМодуляДляСборки = КаталогИнструментов + "\lib\TemplateEpf\ObjectModule.txt";
	
	//ФайлВременноеИмяМодуля = Новый Файл(СтруктураОписанияEpf.ВременноеИмяМодуля);
	ПутьКИсходникам = СтруктураОписанияEpf.КаталогИсходников;
	
	
	
	ИмяФайлаМодуляДляСборки = ПутьКИсходникам + "\ObjectModule.txt";
	Если ГенерироватьУФ Тогда
		ИмяФайлаМодуляДляСборки = ПутьКИсходникам + "\und\70e297e0-e8a2-43bf-8be1-62e408f610a1.0";
	КонецЕсли;	 
	
	УдалитьФайлы(ИмяФайлаМодуляДляСборки);
	ПереместитьФайл(СтруктураОписанияEpf.ВременноеИмяМодуля,ИмяФайлаМодуляДляСборки);
	Отладка("Переименовал в " + ИмяФайлаМодуляДляСборки);
	
	
	//ИмяФайлОсноваОбработкиTemplate = КаталогИнструментов + "\lib\TemplateEpf\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
	//ИмяФайлОсноваОбработки         = КаталогИнструментов + "\lib\TemplateEpf\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	ИмяФайлОсноваОбработкиTemplate = ПутьКИсходникам + "\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
	ИмяФайлОсноваОбработки         = ПутьКИсходникам + "\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	Если ГенерироватьУФ Тогда
		ИмяФайлОсноваОбработкиTemplate = КаталогИнструментов + "\lib\TemplateEpfUF\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
		ИмяФайлОсноваОбработки         = КаталогИнструментов + "\lib\TemplateEpfUF\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	КонецЕсли;	 
	
	Файл_template = Новый Файл(ИмяФайлОсноваОбработкиTemplate);
	Если Файл_template.Существует() Тогда
		//это значит обработка создаётся в первый раз
		КопироватьФайл(ИмяФайлОсноваОбработкиTemplate,ИмяФайлОсноваОбработки);
		ЗаменитьСтрокиВФайлеОсновыОбработки(ИмяФайлОсноваОбработки,СтруктураОписанияEpf.ИмяФичи);
	КонецЕсли;	 
	
	
	ИмяВременнойEPF = ПолучитьИмяВременногоФайла("epf");
	
	ФайлРеальногоEPF = Новый Файл(СтруктураОписанияEpf.ИмяФайлаEpf);
	СоздатьКаталогЕслиЕгоНет(ФайлРеальногоEPF.Путь);
	
	ФайлУжеЕсть = ФайлРеальногоEPF.Существует();
	
	Если ФайлУжеЕсть Тогда
		СделатьСообщение("Пересоздаю " + СтруктураОписанияEpf.ИмяФайлаEpf);
	Иначе	
		СделатьСообщение("Создаю " + СтруктураОписанияEpf.ИмяФайлаEpf);
	КонецЕсли; 
	СтрокаСборкиEpf = "python " + КаталогИнструментов + "\vendor\precommit1c\pyv8unpack.py --compile """ +  ПутьКИсходникам  + """ """ + ИмяВременнойEPF + """";
	//Если ГенерироватьУФ Тогда
	//	СтрокаСборкиEpf = "python " + КаталогИнструментов + "\vendor\precommit1c\pyv8unpack.py --compile " +  КаталогИнструментов + "\lib\TemplateEpfUF " + СтруктураОписанияEpf.ИмяФайлаEpf;
	//КонецЕсли;	 
	Отладка("СтрокаСборкиEpf="+СтрокаСборкиEpf);
	
	
	ФайлВременногоEPF = Новый Файл(ИмяВременнойEPF);
	
	
	//retCode = "";
	//ЗапуститьПриложение(СтрокаСборкиEpf,,Истина,retCode);
	//КомандаСистемы(СтрокаСборкиEpf);
	ВыполнитьКомандуОС(СтрокаСборкиEpf);
	Если ФайлВременногоEPF.Существует() Тогда
		Если ФайлРеальногоEPF.Существует() Тогда
			УдалитьФайлы(ФайлРеальногоEPF.ПолноеИмя);
		КонецЕсли;	 
		КопироватьФайл(ФайлВременногоEPF.ПолноеИмя,ФайлРеальногоEPF.ПолноеИмя);
		Отладка("Файл " + ФайлРеальногоEPF.ПолноеИмя + " создан.");
	Иначе	
		СделатьСообщение("Ошибка создания файла " + ФайлРеальногоEPF.ПолноеИмя + "!!!");
		БылиОшибки = Истина;
	КонецЕсли;	 
	//Сообщить("retCode=" + retCode);
	УдалитьФайлы(ИмяФайлаМодуляДляСборки);
	УдалитьФайлы(ИмяФайлОсноваОбработки);
	УдалитьФайлы(ФайлВременногоEPF.ПолноеИмя);
	

КонецПроцедуры

Функция ПолучитьСледующуюСтрокуМодуля(СтрТзн,Тзн)
	Индекс = Тзн.Индекс(СтрТзн);
	Если Индекс = Тзн.Количество()-1 Тогда
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Тзн.Получить(Индекс+1);
КонецФункции

Процедура ДобавитьСнипет(Знач ID,Знач СтрокаРеальнойПроцедуры,Знач ИмяФайла,БылиОшибки,ТаблицаИзвестныхStepDefinition)
	
	СтрокаРеальнойПроцедуры = СокрЛП(СтрокаРеальнойПроцедуры);
	ID                      = СокрЛП(ID);
	
	//уберем слово "Экспорт"
	Если Прав(НРег(СтрокаРеальнойПроцедуры),7) = "экспорт" Тогда
		СтрокаРеальнойПроцедуры = Лев(СтрокаРеальнойПроцедуры,СтрДлина(СтрокаРеальнойПроцедуры)-7);
		СтрокаРеальнойПроцедуры = СокрЛП(СтрокаРеальнойПроцедуры);
	КонецЕсли;
	
	Если Лев(НРег(СтрокаРеальнойПроцедуры),9) = "процедура" Тогда
		СтрокаРеальнойПроцедуры = СокрЛП(Сред(СтрокаРеальнойПроцедуры,10));
	КонецЕсли;
	
	//Сообщить("ID="+ID);
	//Сообщить("СтрокаРеальнойПроцедуры="+СтрокаРеальнойПроцедуры);
	//Сообщить("ИмяФайла="+ИмяФайла);
	
	Поз = Найти(ID,"(");
	СтрПараметры = Сред(ID,Поз+1);
	СтрПараметры = Лев(СтрПараметры,СтрДлина(СтрПараметры)-1);
	
	//Сообщить("СтрПараметры="+СтрПараметры);
	
	МассивПром = РазложитьСтрокуВМассивПодстрок(СтрПараметры, ",");
	МассивПараметров = Новый Массив;
	Для Каждого Элем Из МассивПром Цикл
		СтруктураПарам = Новый Структура;
		Тип = "Строка";
		Если Найти(НРег(Элем),"число") > 0 Тогда
			Тип = "Число";
		КонецЕсли;
		Если Найти(НРег(Элем),"дата") > 0 Тогда
			Тип = "Дата";
		КонецЕсли;
		СтруктураПарам.Вставить("Тип",Тип);
		МассивПараметров.Добавить(СтруктураПарам);
		
		//Сообщить("Тип="+Тип + ", Элем=" + Элем);
	КонецЦикла;
	
	ПромСтр = ТаблицаИзвестныхStepDefinition.Найти(ID,"ID");
	Если ПромСтр <> Неопределено Тогда
		Если НРег(ПромСтр.ИмяФайла) = НРег(ИмяФайла) Тогда //значит этот снипет из того же файла
			Возврат;
		КонецЕсли;	
	КонецЕсли;	 
	
	Если ПромСтр <> Неопределено Тогда
		БылиОшибки = Истина;
		СделатьСообщение("Ошибка в файле " + ИмяФайла + ", снипет " + ID + " уже был в " + ПромСтр.ИмяФайла);
		Возврат;
	КонецЕсли;
	
	СтрТаблицаИзвестныхStepDefinition                         = ТаблицаИзвестныхStepDefinition.Добавить();
	СтрТаблицаИзвестныхStepDefinition.ID                      = ID;
	СтрТаблицаИзвестныхStepDefinition.СтрокаРеальнойПроцедуры = СтрокаРеальнойПроцедуры;
	СтрТаблицаИзвестныхStepDefinition.ИмяФайла                = ИмяФайла;
	СтрТаблицаИзвестныхStepDefinition.Параметры               = МассивПараметров;
КонецПроцедуры

Процедура ПолучитьУжеСуществующиеСнипетыИзОбработок(Знач КаталогФич,ТаблицаКонтекстовОбработок,ТаблицаИзвестныхStepDefinition,ТаблицаВерсийEPF,КонтекстVanessaBehavoir);
	
	
	
	Файл = Новый Файл(КаталогФич);
	Если Не Файл.Существует() Тогда
		СделатьСообщение("Ошибка в ПолучитьУжеСуществующиеСнипетыИзОбработок(). Файл/каталог " + КаталогФич + " не существует!");
		Возврат;
	КонецЕсли;	 
	
	
	Если Файл.ЭтоФайл() Тогда
		КаталогФич = Файл.Путь;
	КонецЕсли;	 
	
	Файл = Новый Файл(КаталогФич);
	
	БылиОшибки = Ложь;
	НачальныйКаталог = КаталогФич;
	КаталогПоиска    = НачальныйКаталог;
	
	Файл = Новый Файл(НачальныйКаталог);
	Если НРег(Файл.Расширение) = ".feature" Тогда
		КаталогПоиска = Файл.Путь;
	КонецЕсли;	 
	
	Отладка("Ищу снипеты в каталоге " + КаталогПоиска);
	
	//Сообщить("КаталогПоиска="+КаталогПоиска);
	МассивФайлов = НайтиФайлы(КаталогПоиска,"*.epf",Истина);
	Для Каждого Файл Из МассивФайлов Цикл
		//СтрТаблицаКонтекстовОбработок           = ТаблицаКонтекстовОбработок.Добавить();
		//СтрТаблицаКонтекстовОбработок.ИмяФайла  = Файл.ПолноеИмя;
		//СтрТаблицаКонтекстовОбработок.Обработка = ВнешниеОбработки.Создать(СтрТаблицаКонтекстовОбработок.ИмяФайла);
		
		
		//Сообщить("НЕ РЕАЛИЗОВАНО ПолучитьУжеСуществующиеСнипетыИзОбработок!!!");
		
		ВерсияФайла = Файл.ПолучитьВремяИзменения();
		
		
		СтрТаблицаВерсийEPF = ТаблицаВерсийEPF.Найти(Файл.ПолноеИмя,"ИмяФайла");
		Если СтрТаблицаВерсийEPF = Неопределено Тогда
			СтрТаблицаВерсийEPF             = ТаблицаВерсийEPF.Добавить();
			СтрТаблицаВерсийEPF.ИмяФайла    = Файл.ПолноеИмя;
			СтрТаблицаВерсийEPF.ВерсияФайла = ВерсияФайла;
		Иначе	
			Если СтрТаблицаВерсийEPF.ВерсияФайла <> ВерсияФайла Тогда
				//значит файл изменился
				//обновляем версию и удаляем старые снипеты
				СтрТаблицаВерсийEPF.ВерсияФайла = ВерсияФайла;
				
				Отбор = Новый Структура;
				Отбор.Вставить("ИмяФайла",Файл.ПолноеИмя);
				МассивСтрок = ТаблицаИзвестныхStepDefinition.НайтиСтроки(Отбор);
				
				Для каждого СтрокаТаблицы Из МассивСтрок Цикл
					ТаблицаИзвестныхStepDefinition.Удалить(СтрокаТаблицы);
				КонецЦикла;
				
				Отладка("Обновил версию! " + Файл.ПолноеИмя);
			Иначе
				//значит уже актуальная версия файла загружена
				//Сообщить("!!!!!!!!!!!!!!!!!!! " + Файл.ПолноеИмя);
				Продолжить;
			КонецЕсли; 
		КонецЕсли; 
		
		
		
		
		Попытка
			Обработка = ВнешниеОбработки.Создать(Файл.ПолноеИмя);
			МассивСнипетовИзОбработки = Обработка.ПолучитьСписокТестов(КонтекстVanessaBehavoir);
		Исключение
			Отладка("Не смог получить список шагов в обработке: " + Файл.ПолноеИмя);
			Отладка("" + ОписаниеОшибки());
			//Сообщить("Не смог загрузить снипеты из " + Файл.ПолноеИмя);
			//Сообщить(ОписаниеОшибки());
			Продолжить;
		КонецПопытки;
		
		
		СтрТаблицаКонтекстовОбработок = Новый Структура;
		СтрТаблицаКонтекстовОбработок.Вставить("ИмяФайла",Файл.ПолноеИмя);
		СтрТаблицаКонтекстовОбработок.Вставить("Обработка",Обработка);
		ТаблицаКонтекстовОбработок.Добавить(СтрТаблицаКонтекстовОбработок);
		
		Для каждого Снипет Из МассивСнипетовИзОбработки Цикл
			ДобавитьСнипет(Снипет.Снипет,Снипет.ИмяПроцедуры,Файл.ПолноеИмя,БылиОшибки,ТаблицаИзвестныхStepDefinition);
		КонецЦикла;
		
		Продолжить;
		
		
		//Отладка("Путь="+Файл.ПолноеИмя);
		//Стр = Файл.Путь;
		//Стр = СтрЗаменить(Стр,КаталогИнструментов,КаталогИнструментов + "\Src");
		//Стр = Стр + "" + Файл.ИмяБезРасширения + "\ObjectModule.txt";
		////Сообщить("Стр="+Стр);
		//
		//ФайлМодуль = Новый Файл(Стр);
		//Если Не ФайлМодуль.Существует() Тогда
		//	//значит мы не можем найти исходники epf и распакуем epf сами
		//	//ПрерватьВыполнениеСкрипта("Файл " + Стр + " не найден! Не могу найти StepDefinition.");
		//	Стр = РаспаковатьEPF(Файл.ПолноеИмя);
		//	Если Стр = Неопределено Тогда
		//		СделатьСообщение("Для " + Файл.ПолноеИмя + " не были получены исходники!");
		//	КонецЕсли;	 
		//	//ПрерватьВыполнениеСкрипта("Файл " + Стр + " не найден! Не могу найти StepDefinition.");
		//КонецЕсли;
		//
		//ТелоМодуля = ЗагрузитьТелоМодуляВТаблицуЗначений(Стр);
		//
		//Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
		//	Если Лев(СтрТелоМодуля.Стр,3) = "//@" Тогда
		//		СледСтрока = ПолучитьСледующуюСтрокуМодуля(СтрТелоМодуля,ТелоМодуля);
		//		Если СледСтрока = Неопределено Тогда
		//			Продолжить;
		//		КонецЕсли;
		//		ДобавитьСнипет(Сред(СтрТелоМодуля.Стр,4),СледСтрока.Стр,Файл.ПолноеИмя,БылиОшибки,ТаблицаИзвестныхStepDefinition);
		//		//Сообщить("" + СтрТелоМодуля.Стр);
		//	КонецЕсли;
		//КонецЦикла;
		
	КонецЦикла;
	
	Если БылиОшибки Тогда
		Сообщить("Были ошибки в ПросканироватьИсходникиИНайтиВсеStepDefinition.");
	КонецЕсли;
	
КонецПроцедуры

Функция СоздатьСтруктуруСнипета()
	СтруктураСнипета = Новый Структура;
	
	Возврат СтруктураСнипета;
КонецФункции

Процедура УбратьЗапрещенныеСимволыИзStepDefinition(StepDefinition) 
	StepDefinition = СтрЗаменить(StepDefinition,".","");
	StepDefinition = СтрЗаменить(StepDefinition,",","");
	StepDefinition = СтрЗаменить(StepDefinition,":","");
	StepDefinition = СтрЗаменить(StepDefinition,";","");
	StepDefinition = СтрЗаменить(StepDefinition,"-","_");
	StepDefinition = СтрЗаменить(StepDefinition,"+","");
	StepDefinition = СтрЗаменить(StepDefinition,"/","");
	StepDefinition = СтрЗаменить(StepDefinition,"\","");
	StepDefinition = СтрЗаменить(StepDefinition,"=","");
	StepDefinition = СтрЗаменить(StepDefinition,"!","");
	StepDefinition = СтрЗаменить(StepDefinition,"@","");
	StepDefinition = СтрЗаменить(StepDefinition,"#","");
	StepDefinition = СтрЗаменить(StepDefinition,"$","");
	StepDefinition = СтрЗаменить(StepDefinition,"%","");
	StepDefinition = СтрЗаменить(StepDefinition,"^","");
	StepDefinition = СтрЗаменить(StepDefinition,"&","");
	StepDefinition = СтрЗаменить(StepDefinition,"*","");
	StepDefinition = СтрЗаменить(StepDefinition,"(","");
	StepDefinition = СтрЗаменить(StepDefinition,")","");
	StepDefinition = СтрЗаменить(StepDefinition,"№","");
	StepDefinition = СтрЗаменить(StepDefinition,"?","");
	StepDefinition = СтрЗаменить(StepDefinition,"`","");
	StepDefinition = СтрЗаменить(StepDefinition,"'","");
	StepDefinition = СтрЗаменить(StepDefinition,"~","");
	StepDefinition = СтрЗаменить(StepDefinition,Символы.НПП," ");
	//StepDefinition = СтрЗаменить(StepDefinition,"<","");
	//StepDefinition = СтрЗаменить(StepDefinition,">","");
КонецПроцедуры

Функция ДобавитьНолейВСтроку(Знач Стр,Длина);
	Пока СтрДлина(Стр) < Длина Цикл
		Стр = "0" + Стр;
	КонецЦикла;
	
	Возврат Стр;
КонецФункции	


Функция ДобавитьПараметрStepDefinition(Знач Стр,КолПараметров) Экспорт
	КолПараметровСтр = СокрЛП(КолПараметров);
	КолПараметровСтр = ДобавитьНолейВСтроку(КолПараметровСтр,2);
	//Если СтрДлина(КолПараметровСтр) = 1 Тогда
	//	КолПараметровСтр = "0" + КолПараметровСтр;
	//КонецЕсли;
	
	Если (Найти(Стр,"<ПараметрЧисло>") > 0) или (Найти(Стр,"<ПараметрСтрокаА>") > 0) или (Найти(Стр,"<ПараметрСтрокаК>") > 0) или (Найти(Стр,"<ПараметрДата>") > 0) Тогда
		Стр = СтрЗаменить(Стр,"<Параметр","<Парам" + КолПараметровСтр) + ",";
	Иначе	
		Стр = Стр + ",";
	КонецЕсли;	 
	Стр = СтрЗаменить(Стр,"<","");
	Стр = СтрЗаменить(Стр,">","");
	
	Возврат Стр;
КонецФункции

Функция СделатьПервуюБуквуЗаглавной(Стр) Экспорт
	Если СтрДлина(Стр) = 0 Тогда
		Возврат Стр;
	КонецЕсли;
	
	ПерваяБуква = ВРег(Лев(Стр,1));
	
	Возврат ПерваяБуква + Сред(Стр,2);
КонецФункции

Процедура ОбработатьСтрокиЭмуляцияRegExp(Стр,ПараметрыСтроки,Символ);
	ПромСтр = Стр;
	НоваяСтрока = "";
	Поз = Найти(ПромСтр,Символ);
	
	Если Поз = 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	Пока Поз > 0 Цикл
		НоваяСтрока = НоваяСтрока + Лев(ПромСтр,Поз-1);
		ПромСтр = Сред(ПромСтр,Поз+1);
		
		Поз = Найти(ПромСтр,Символ);
		Если Поз > 0 Тогда
			ЗначениеПараметра = Лев(ПромСтр,Поз-1);
			//Сообщить("ЗначениеПараметра="+ЗначениеПараметра);
			ПромСтр = Сред(ПромСтр,Поз+1);
			Если Символ = "'" Тогда
				НоваяСтрока = НоваяСтрока + " <ПараметрСтрокаА> ";
			Иначе	
				НоваяСтрока = НоваяСтрока + " <ПараметрСтрокаК> ";
			КонецЕсли; 
			ПараметрыСтроки.Добавить(ЗначениеПараметра);
		Иначе
			НоваяСтрока = НоваяСтрока + ПромСтр;
		КонецЕсли;	 
		
		
		Поз = Найти(ПромСтр,Символ);
		Если Поз = 0 Тогда
			НоваяСтрока = НоваяСтрока + ПромСтр;
		КонецЕсли;	 
	КонецЦикла;
	
	Стр = НоваяСтрока;
КонецПроцедуры

Функция ЭтоЦелоеЧисло(Стр)
	Для Ккк = 1 По СтрДлина(Стр) Цикл
		Символ = Сред(Стр,Ккк,1);
		Если    Символ = "0"
			Или Символ = "1"
			Или Символ = "2"
			Или Символ = "3"
			Или Символ = "4"
			Или Символ = "5"
			Или Символ = "6"
			Или Символ = "7"
			Или Символ = "8"
			Или Символ = "9"
			Тогда
			//это цифра
		Иначе
			Возврат Ложь;	
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Истина;
КонецФункции

Процедура ОбработатьДатыЭмуляцияRegExp(Стр,ПараметрыДаты)
	Массив = РазложитьСтрокуВМассивПодстрок(Стр,".");
	
	Для Ккк = 0 По Массив.Количество()-1-2 Цикл
		Элем1 = Прав(Массив[Ккк],2);
		Элем2 = Массив[Ккк+1];
		Элем3 = Лев(Массив[Ккк+2],4);
		Если СтрДлина(Элем3) < 4 Тогда
			Элем3 = Лев(Массив[Ккк+2],2);
		КонецЕсли;	 
		Если СтрДлина(Элем3) = 4 Тогда
			Если НЕ ЭтоЦелоеЧисло(Элем3) Тогда
				Элем3 = Лев(Массив[Ккк+2],2);
			КонецЕсли;	 
		КонецЕсли;	 
		
		Если СтрДлина(Элем1) <>  2 Тогда
			Продолжить;
		КонецЕсли;	 
		Если СтрДлина(Элем2) <>  2 Тогда
			Продолжить;
		КонецЕсли;	 
		Если (СтрДлина(Элем3) = 2) или (СтрДлина(Элем3) = 4) Тогда
		Иначе
			Продолжить;
		КонецЕсли;	 
		
		Если НЕ ЭтоЦелоеЧисло(Элем1) Тогда
			Продолжить;
		КонецЕсли;	 
		Если НЕ ЭтоЦелоеЧисло(Элем2) Тогда
			Продолжить;
		КонецЕсли;	 
		Если НЕ ЭтоЦелоеЧисло(Элем3) Тогда
			Продолжить;
		КонецЕсли;	 
		
		
		СтрДат = "" + Элем1 + "." + Элем2 + "." +Элем3;
		
		Поз = Найти(Стр,СтрДат);
		Если Поз > 0 Тогда
			Стр = Лев(Стр,Поз-1) + " <ПараметрДата> " + Сред(Стр,Поз+СтрДлина(СтрДат));
			//Сообщить("ЗначениеПараметра="+СтрДат);
			ПараметрыДаты.Добавить(СтрДат);
			ОбработатьДатыЭмуляцияRegExp(Стр,ПараметрыДаты);
			Прервать;
		КонецЕсли;	 
		
		//Если ЭтоЦелоеЧисло(Элем1) и  Тогда
		//КонецЕсли;	 
	КонецЦикла;
	
КонецПроцедуры

Функция ЭтоКорректноеЧисло(Стр)
	Если Стр = "" Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	ДлинаСтроки = СтрДлина(Стр);
	Для Ккк=1 По ДлинаСтроки Цикл
		Символ = Сред(Стр,Ккк,1);
		Если    Символ = "0"
			Или Символ = "1"
			Или Символ = "2"
			Или Символ = "3"
			Или Символ = "4"
			Или Символ = "5"
			Или Символ = "6"
			Или Символ = "7"
			Или Символ = "8"
			Или Символ = "9"
			Или Символ = "."
			Или Символ = "-"
			Тогда
		Иначе
			Возврат Ложь;
		КонецЕсли;	 
	КонецЦикла;
	
	
	Поз = Найти(Стр,".");
	Если Поз > 0 Тогда
		ЧастьСтрокиСлева = Лев(Стр,Поз-1);
		Если СтрДлина(ЧастьСтрокиСлева) = 0 Тогда
			Возврат Ложь;
		КонецЕсли;  
		
		ЧастьСтрокиСправа = Сред(Стр,Поз+1);
		Если СтрДлина(ЧастьСтрокиСправа) = 0 Тогда
			Возврат Ложь;
		КонецЕсли;  
	КонецЕсли;  
	
	
	Если Найти(Стр,".") > 0 Тогда
		ПромСтр = СтрЗаменить(Стр,".","");
		Если СтрДлина(Стр) <> (СтрДлина(ПромСтр)+1) Тогда
			//должна быть только одна точка в числе
			Возврат Ложь;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Найти(Стр,"-") > 0 Тогда
		Если Лев(Стр,1) <> "-" Тогда
			Возврат Ложь; //минус может быть только первым символом
		КонецЕсли;	 
		
		ПромСтр = СтрЗаменить(Стр,"-","");
		Если СтрДлина(Стр) <> (СтрДлина(ПромСтр)+1) Тогда
			//должна быть только минус в числе
			Возврат Ложь;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если СтрДлина(Стр) > 1 Тогда
		Если Лев(Стр,1) = "0" Тогда //значит это строка, которая начинается с нуля
			Возврат Ложь;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Возврат Истина;
	
	//Попытка
	//	ПромЧисло = Число(Стр);
	//Исключение
	//	Возврат Ложь;
	//КонецПопытки;
	//
	//ПромСтрока = Строка(ПромЧисло);
	//
	//ПромСтрока = СтрЗаменить(ПромСтрока,Символы.НПП,"");
	//ПромСтрока = СтрЗаменить(ПромСтрока,",",".");
	//
	//
	//Если ПромСтрока = СокрЛП(Стр) Тогда
	//	Возврат Истина;
	//КонецЕсли;	 
	//
	//Возврат Ложь;
КонецФункции

Процедура ОбработатьЧислаЭмуляцияRegExp(Стр,ПараметрыЧисла)
	ПромСтр           = Стр;
	СтрокаРезультат   = "";
	НакопленнаяСтрока = "";
	ПредыдущийСимвол = Неопределено;
	
	Для Ккк = 1 По СтрДлина(ПромСтр) Цикл
		Символ = Сред(ПромСтр,Ккк,1);
		
		Если Ккк > 1 Тогда
			ПредыдущийСимвол = Сред(ПромСтр,Ккк-1,1);
		КонецЕсли;	 
		
		Если ЭтоЦелоеЧисло(Символ) или ((Символ = "-") и (Найти(НакопленнаяСтрока,"-") = 0)) Тогда
			Если НакопленнаяСтрока = "" Тогда
				Если (ПредыдущийСимвол = " ") или (ПредыдущийСимвол = "-") или (Ккк = 1) Тогда //всё хорошо, мы нашли начало числа
				Иначе
					СтрокаРезультат = СтрокаРезультат + Символ;
					НакопленнаяСтрока = "";
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			НакопленнаяСтрока = НакопленнаяСтрока + Символ;
			Продолжить;
		КонецЕсли;	 
		
		НакопленнаяСтрока = НакопленнаяСтрока + Символ;
		
		Если Символ = "." Тогда
			Продолжить;
		КонецЕсли;	 
		
		ПолученноеЗначение = Лев(НакопленнаяСтрока,СтрДлина(НакопленнаяСтрока)-1);
		Если ЭтоКорректноеЧисло(ПолученноеЗначение) и ((Символ = " ") или (Символ = ",") или (Символ = ";") или (Символ = ":")) Тогда
			СтрокаРезультат = СтрокаРезультат + " <ПараметрЧисло> ";
			ПараметрыЧисла.Добавить(ПолученноеЗначение);
			//Сообщить("ЗначениеПараметра="+НакопленнаяСтрока);
			НакопленнаяСтрока = "";
		Иначе
			СтрокаРезультат =СтрокаРезультат + НакопленнаяСтрока;
			НакопленнаяСтрока = "";
		КонецЕсли;	 
	КонецЦикла;
	
	Если СтрДлина(НакопленнаяСтрока) > 0 Тогда
		Если ЭтоКорректноеЧисло(НакопленнаяСтрока) Тогда
			СтрокаРезультат = СтрокаРезультат + " <ПараметрЧисло> ";
			ПараметрыЧисла.Добавить(НакопленнаяСтрока);
			//Сообщить("ЗначениеПараметра="+НакопленнаяСтрока);
		Иначе
			СтрокаРезультат =СтрокаРезультат + НакопленнаяСтрока;
		КонецЕсли;
	КонецЕсли;	 
	
	Стр = СтрокаРезультат;
КонецПроцедуры

Процедура ОбработатьПараметрыИменованные(Стр,ПараметрыИменованные)
	
	МассивТекПараметров = Новый Массив;
	
	Пока Истина Цикл
		Поз1 = Найти(Стр,"<");
		Поз2 = Найти(Стр,">");
		
		Если (Поз1 > 0) И (Поз2 > 0) и ((Поз2-Поз1) > 1) Тогда
			СтрПараметр = СокрЛП(Сред(Стр,Поз1+1,Поз2-Поз1-1));
			
			//ПараметрыИменованные.Добавить(СтрПараметр);
			
			
			ТекПараметр = "|||"+СтрПараметр + "|||";
			
			СтруктураПараметра = Новый Структура;
			СтруктураПараметра.Вставить("Имя",СтрЗаменить(СтрПараметр," ","|||ЗаменаПробела|||"));
			СтруктураПараметра.Вставить("ЗначениеВСтроке",ТекПараметр);
			
			МассивТекПараметров.Добавить(СтруктураПараметра);
			
			
			Стр = СтрЗаменить(Стр,"<" + СтрПараметр + ">",ТекПараметр);
			
			//ПромСтр = Сред(ПромСтр,Поз2+1);
		Иначе	
			Прервать;
		КонецЕсли; 
		
	КонецЦикла;
	
	Ном = 0;
	Для каждого Элем Из МассивТекПараметров Цикл
		Ном = Ном+1;
		//КолПараметровСтр = Ном;
		//Если СтрДлина(КолПараметровСтр) = 1 Тогда
		//	КолПараметровСтр = "0" + КолПараметровСтр;
		//КонецЕсли;
		Стр = СтрЗаменить(Стр,Элем.ЗначениеВСтроке,"<" + Элем.Имя + ">");
		
		ПараметрыИменованные.Добавить(Элем.Имя);
	КонецЦикла;
	
	
КонецПроцедуры

Функция ПолучитьStepDefinitionПоСтроке(Знач Стр,ЗначенияПараметров, СтрокаПараметров = "",ЕстьПараметрыТаблицы = Ложь) 
	
	ПараметрыЧисла       = Новый Массив;
	ПараметрыСтрокиА     = Новый Массив;
	ПараметрыСтрокиК     = Новый Массив;
	ПараметрыДаты        = Новый Массив;
	ПараметрыИменованные = Новый Массив;
	
	//Стр = СтрЗаменить(Стр,"""","'");//чтобы " заменить на апостроф
	
	
	//Сообщить("Обрабатываю " + Стр);
	ОбработатьСтрокиЭмуляцияRegExp(Стр,ПараметрыСтрокиА,"'");
	ОбработатьСтрокиЭмуляцияRegExp(Стр,ПараметрыСтрокиК,"""");
	//Сообщить("Получил " + Стр);
	//Сообщить(" ");
	
	//Сообщить("Обрабатываю " + Стр);
	ОбработатьДатыЭмуляцияRegExp(Стр,ПараметрыДаты);
	//Сообщить("Получил " + Стр);
	//Сообщить(" ");
	
	//Сообщить("Обрабатываю " + Стр);
	ОбработатьЧислаЭмуляцияRegExp(Стр,ПараметрыЧисла);
	//Сообщить("Получил " + Стр);
	//Сообщить(" ");
	
	
	ОбработатьПараметрыИменованные(Стр,ПараметрыИменованные);
	//Сообщить("Получил " + Стр);
	//Сообщить(" ");
	
	
	УбратьЗапрещенныеСимволыИзStepDefinition(стр);
	
	
	
	
	
	
	МассивПодстрок = РазложитьСтрокуВМассивПодстрок(Стр," ",Истина);
	КолПараметров        = 0;
	КолПараметровЧисло   = 0;
	КолПараметровСтрокаА = 0;
	КолПараметровСтрокаК = 0;
	КолПараметровДата    = 0;
	
	КолПараметровИменованные = 0;
	
	СтрокаПараметров    = "";
	//args                = "";
	StepDefinition      = "";
	
	//ЗначенияПараметров = Новый Массив;
	
	Для Каждого Элем Из МассивПодстрок Цикл
		//Сообщить("Элем="+Элем);
		Если Элем = "<ПараметрСтрокаА>" Тогда
			КолПараметров        = КолПараметров       + 1;
			КолПараметровСтрокаА = КолПараметровСтрокаА + 1;
			
			СтрокаПараметров = СтрокаПараметров + ДобавитьПараметрStepDefinition(Элем,КолПараметров);
			
			СтруктураЗначенияПараметра = Новый Структура;
			СтруктураЗначенияПараметра.Вставить("Значение",ПараметрыСтрокиА[КолПараметровСтрокаА-1]);
			СтруктураЗначенияПараметра.Вставить("Тип","Строка");
			
			ЗначенияПараметров.Добавить(СтруктураЗначенияПараметра);
			
			Продолжить;
		КонецЕсли;
		Если Элем = "<ПараметрСтрокаК>" Тогда
			КолПараметров        = КолПараметров       + 1;
			КолПараметровСтрокаК = КолПараметровСтрокаК + 1;
			
			СтрокаПараметров = СтрокаПараметров + ДобавитьПараметрStepDefinition(Элем,КолПараметров);
			
			СтруктураЗначенияПараметра = Новый Структура;
			СтруктураЗначенияПараметра.Вставить("Значение",ПараметрыСтрокиК[КолПараметровСтрокаК-1]);
			СтруктураЗначенияПараметра.Вставить("Тип","Строка");
			
			ЗначенияПараметров.Добавить(СтруктураЗначенияПараметра);
			
			Продолжить;
		КонецЕсли;
		Если Элем = "<ПараметрЧисло>" Тогда
			КолПараметров      = КолПараметров      + 1;
			КолПараметровЧисло = КолПараметровЧисло + 1;
			
			СтрокаПараметров = СтрокаПараметров + ДобавитьПараметрStepDefinition(Элем, КолПараметров);
			
			СтруктураЗначенияПараметра = Новый Структура;
			СтруктураЗначенияПараметра.Вставить("Значение",ПараметрыЧисла[КолПараметровЧисло-1]);
			СтруктураЗначенияПараметра.Вставить("Тип","Число");
			
			ЗначенияПараметров.Добавить(СтруктураЗначенияПараметра);
			//args             = args + ПараметрыЧисла[КолПараметровЧисло-1] + ",";
			Продолжить;
		КонецЕсли;
		Если Элем = "<ПараметрДата>" Тогда
			КолПараметров      = КолПараметров      + 1;
			КолПараметровДата  = КолПараметровДата  + 1;
			
			СтрокаПараметров = СтрокаПараметров + ДобавитьПараметрStepDefinition(Элем,КолПараметров);
			
			СтруктураЗначенияПараметра = Новый Структура;
			СтруктураЗначенияПараметра.Вставить("Значение",ПараметрыДаты[КолПараметровДата-1]);
			СтруктураЗначенияПараметра.Вставить("Тип","Дата");
			
			ЗначенияПараметров.Добавить(СтруктураЗначенияПараметра);
			//args             = args + ПараметрыДаты[КолПараметровДата-1] + ",";
			Продолжить;
		КонецЕсли;
		
		НашлиПараметрИменованный = Ложь;
		Для каждого ЭлемПараметрыИменованные Из ПараметрыИменованные Цикл
			ЭлемПараметрыИменованные = СтрЗаменить(ЭлемПараметрыИменованные,"|||ЗаменаПробела|||"," ");
			Элем                     = СтрЗаменить(Элем,"|||ЗаменаПробела|||"," ");
			
			СтрДляСравнения = "<" + ЭлемПараметрыИменованные + ">";
			Если СтрДляСравнения = Элем Тогда
				КолПараметров            = КолПараметров      + 1;
				КолПараметровИменованные = КолПараметровИменованные  + 1;
				
				СтрокаПараметров = СтрокаПараметров + ДобавитьПараметрStepDefinition(Элем,КолПараметров);
				
				СтруктураЗначенияПараметра = Новый Структура;
				СтруктураЗначенияПараметра.Вставить("Значение",ЭлемПараметрыИменованные);
				СтруктураЗначенияПараметра.Вставить("Тип","ПараметрИменованный");
				
				ЗначенияПараметров.Добавить(СтруктураЗначенияПараметра);
				
				НашлиПараметрИменованный = Истина;
				Прервать;
			КонецЕсли; 
			
		КонецЦикла;
		Если НашлиПараметрИменованный Тогда
			Продолжить;
		КонецЕсли; 
		
		StepDefinition = StepDefinition + СделатьПервуюБуквуЗаглавной(Элем);
	КонецЦикла;
	
	
	Если ЕстьПараметрыТаблицы  = Истина Тогда
		СтрокаПараметров = СтрокаПараметров + "ТабПарам,"; 
	КонецЕсли;	 
	
	Если СтрокаПараметров <> "" Тогда
		Если Прав(СтрокаПараметров,1) = "," Тогда
			СтрокаПараметров = Лев(СтрокаПараметров,СтрДлина(СтрокаПараметров)-1);//там лишняя запятая
		КонецЕсли;	 
	КонецЕсли;
	
	УбратьЗапрещенныеСимволыИзStepDefinition(StepDefinition);
	ПроверкаКорректностиStepDefinition(StepDefinition);
	
	StepDefinition = StepDefinition + "(" + СтрокаПараметров + ")";
	
	//Если СтрДлина(args) > 0 Тогда
	//	args = Лев(args,СтрДлина(args)-1);//убрали запятую
	//КонецЕсли;
	//Сообщить("args="+args);
	
	
	Возврат StepDefinition;
	//Сообщить(стр);
КонецФункции

Процедура ПроверкаКорректностиStepDefinition(StepDefinition)
	ПервыйСимвол = Лев(StepDefinition,1);
	Если ЭтоЦелоеЧисло(ПервыйСимвол) Тогда
		StepDefinition = "_" + StepDefinition;
	КонецЕсли;	 
КонецПроцедуры

Функция СнипетыПолучитьСнипетыПоШагам(Шаги) Экспорт
	МассивСнипетов = Новый Массив;
	
	МассивПовторов = Новый Массив;
	
	Для каждого СтрШаг Из Шаги Цикл
		//Если СокрЛП(СтрШаг.АдресСнипета) <> "" Тогда
		//	Продолжить;
		//КонецЕсли; 
		//args = Неопределено;
		ЗначенияПараметров = Новый Массив;
		СтарыйStepDefinition = ПолучитьStepDefinitionПоСтроке(СтрШаг.ИмяШагаБезКлючевогоСлова,ЗначенияПараметров,,СтрШаг.ШагСПараметрамиВТаблице);
		НовыйStepDefinition  = ПолучитьНовыйStepDefinition(СтарыйStepDefinition);
		StepDefinition       = НовыйStepDefinition;
		
		СнипетБезПараметров = Лев(StepDefinition,Найти(StepDefinition,"(")-1);
		Если МассивПовторов.Найти(СнипетБезПараметров) = Неопределено Тогда
			МассивПовторов.Добавить(СнипетБезПараметров);
		Иначе
			Продолжить;
		КонецЕсли;	 
		
		Отладка("По (" + СтрШаг.Имя + ") получил StepDefinition: " + StepDefinition);
		
		СтруктураСнипета = СоздатьСтруктуруСнипета();
		СтруктураСнипета.Вставить("Шаг",СтрШаг.Имя);
		СтруктураСнипета.Вставить("StepDefinition",StepDefinition);
		СтруктураСнипета.Вставить("ЗначенияПараметров",ЗначенияПараметров);
		СтруктураСнипета.Вставить("АдресСнипета",СтрШаг.АдресСнипета);
		
		МассивСнипетов.Добавить(СтруктураСнипета);
	КонецЦикла;
	
	Возврат МассивСнипетов;
КонецФункции

Процедура ДобавитьStepDefinitionВТекстМодуля(СтруктураОписанияEpf,StepDefinition,ПримерИспользованияПроцедуры,ШагСтрокДляМодуля,АдресСнипета,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур,ГенерироватьУФ,ЭтоУФ = Ложь) Экспорт 
	ГенерироватьСнипетЗакоментаренным = ?(СокрЛП(АдресСнипета) = "",Ложь,Истина);
	Если НРег(СтруктураОписанияEpf.ИмяФайлаEpf) = НРег(АдресСнипета) Тогда
		ГенерироватьСнипетЗакоментаренным = Ложь;
	КонецЕсли;	 
	
	Если Не СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур Тогда
		Если ГенерироватьСнипетЗакоментаренным Тогда
			Возврат;
		КонецЕсли;  
	КонецЕсли;  
	
	//Сообщить("СтруктураОписанияEpf.ИмяФичи="+СтруктураОписанияEpf.ИмяФичи);
	//Сообщить("АдресСнипета="+АдресСнипета);
	
	ТелоМодуля = СтруктураОписанияEpf.ТелоМодуля;
	Если ЭтоУФ Тогда
		ТелоМодуля = ЗначениеИзСтрокиВнутр(ТелоМодуля);
	КонецЕсли;	 
	ТелоМодуля.Сортировать("НомСтр");
	
	СтрокаПоискаStepDefinition = НРег(Лев(StepDefinition,Найти(StepDefinition,"(")));//будем искать без параметров
	Если СтрокаПоискаStepDefinition = "" Тогда
		ВызватьИсключение "Ошибка в ДобавитьStepDefinitionВТекстМодуля!";
	КонецЕсли;	 
	
	
	
	УжеЕсть = Ложь;
	Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
		Стр = СокрЛП(СтрТелоМодуля.Стр);
		Если Лев(Стр,3) = "//@" Тогда //так определяется StepDefinition
			Если Найти(НРег(Стр),СтрокаПоискаStepDefinition) > 0 Тогда
				УжеЕсть = Истина;
				Прервать;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
	Если УжеЕсть Тогда
		Возврат;
	КонецЕсли;
	
	//НомСтр = ПолучитьМаксНомерИзТелаМодуля(ТелоМодуля);
	
	//Возврат;
	
	ПрефиксКоментария = ?(ГенерироватьСнипетЗакоментаренным,"//","");
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"");
	Если ГенерироватьУФ Тогда
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "&НаКлиенте");
	КонецЕсли;	 
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "//" + ПримерИспользованияПроцедуры);
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "//@" + StepDefinition);
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "Процедура " + StepDefinition + " Экспорт");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "	//Ванесса.ПосмотретьЗначение(Парам01,Истина);");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "	ВызватьИсключение ""Не реализовано."";");
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКоментария + "КонецПроцедуры");
	
	Если ЭтоУФ Тогда
		//ТелоМодуля = ЗначениеВСтрокуВнутр(ТелоМодуля);
		СтруктураОписанияEpf.ТелоМодуля = ЗначениеВСтрокуВнутр(ТелоМодуля);
	КонецЕсли;	 
КонецПроцедуры

Функция ИнкрементЗначения(Зн,Инкремент)
	Зн = Зн + Инкремент;
	Возврат Зн;
КонецФункции

Процедура ЗаполнитьПроцедуруПолучитьСписокТестов(ТелоМодуля,Снипеты,ЭтоУФ = Ложь,ИмяФайлаФичи,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур) Экспорт
	Если ЭтоУФ Тогда
		ТелоМодуля = ЗначениеИзСтрокиВнутр(ТелоМодуля);
	КонецЕсли;	 
	ТелоМодуля.Сортировать("НомСтр");
	
	
	
	КодПроцедурыПолучитьСписокТестов = Новый ТаблицаЗначений;
	КодПроцедурыПолучитьСписокТестов.Колонки.Добавить("Стр");
	
	
	
	НашелПроцедуруПолучитьСписокТестов = Ложь;
	НомерСтрокиНачалоФункции           = -1; 
	
	НашелКонецФункции                  = Ложь;
	НомерСтрокиКонецФункции            = -1; 
	
	Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
		Стр = НРег(СокрЛП(СтрТелоМодуля.Стр));
		Если (Найти(Стр,"функция") > 0) и (Найти(Стр,"получитьсписоктестов(") > 0) Тогда
			НашелПроцедуруПолучитьСписокТестов = Истина;
			НомерСтрокиНачалоФункции           = СтрТелоМодуля.НомСтр;
			Продолжить;
		КонецЕсли;
		
		
		Если НашелПроцедуруПолучитьСписокТестов Тогда
			СтрКодПроцедурыПолучитьСписокТестов     = КодПроцедурыПолучитьСписокТестов.Добавить();
			СтрКодПроцедурыПолучитьСписокТестов.Стр = СтрТелоМодуля.Стр;
		КонецЕсли;	 
		
		Если НашелПроцедуруПолучитьСписокТестов Тогда
			Если Стр = "конецфункции" Тогда
				НашелКонецФункции       = Истина;
				НомерСтрокиКонецФункции = СтрТелоМодуля.НомСтр;
				Прервать;
			КонецЕсли;
		КонецЕсли; 
	КонецЦикла;
	
	
	Если Не НашелПроцедуруПолучитьСписокТестов Тогда
		СтрОшибки = "Не нашел функцию ""ПолучитьСписокТестов"".";
		Сообщить(СтрОшибки);
		ВызватьИсключение СтрОшибки;
	КонецЕсли;	 
	Если Не НашелКонецФункции Тогда
		СтрОшибки = "Не нашел конец функции ""ПолучитьСписокТестов"".";
		Сообщить(СтрОшибки);
		ВызватьИсключение СтрОшибки;
	КонецЕсли;	 
	
	
	СтрокиДляУдаления = Новый Массив;
	Для каждого СтрКодПроцедурыПолучитьСписокТестов Из КодПроцедурыПолучитьСписокТестов Цикл
		СтрокаКода = СокрЛП(НРег(СтрКодПроцедурыПолучитьСписокТестов.Стр));
		Если Лев(СтрокаКода,2) = "//" Тогда
			СтрокиДляУдаления.Добавить(СтрКодПроцедурыПолучитьСписокТестов);
			Продолжить;
		КонецЕсли;	 
		
		Если Найти(СтрокаКода,НРег("ДобавитьШагВМассивТестов")) = 0 Тогда
			СтрокиДляУдаления.Добавить(СтрКодПроцедурыПолучитьСписокТестов);
			Продолжить;
		КонецЕсли;	 
		
		Нашли = Ложь;
		Для каждого Снипет Из Снипеты Цикл
			StepDefinition = НРег(Снипет.StepDefinition);
			
			Если Найти(СтрокаКода,StepDefinition) > 0 Тогда //значит этот шаг надо удалить из КодПроцедурыПолучитьСписокТестов
				Нашли = Истина;
				Прервать;
			КонецЕсли;	 
		КонецЦикла;
		
		Если Нашли Тогда
			СтрокиДляУдаления.Добавить(СтрКодПроцедурыПолучитьСписокТестов);
		КонецЕсли;	 
	КонецЦикла;
	
	Для каждого СтрКодПроцедурыПолучитьСписокТестов Из СтрокиДляУдаления Цикл
		КодПроцедурыПолучитьСписокТестов.Удалить(СтрКодПроцедурыПолучитьСписокТестов);
	КонецЦикла;
	
	
	
	
	//очистим содержимое функции
	КолСтрок = ТелоМодуля.Количество();
	Для Ккк = 0 По КолСтрок-1 Цикл
		ИдСтроки = КолСтрок - Ккк - 1;
		
		СтрокаМодуля = ТелоМодуля[ИдСтроки];
		Если (СтрокаМодуля.НомСтр > НомерСтрокиНачалоФункции) и (СтрокаМодуля.НомСтр < НомерСтрокиКонецФункции) Тогда
			ТелоМодуля.Удалить(СтрокаМодуля);
		КонецЕсли;	 
	КонецЦикла;
	
	
	
	НомСтр = НомерСтрокиНачалоФункции;
	
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Ванесса = КонтекстФреймворкаBDD;",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	ВсеТесты = Новый Массив;",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"",ИнкрементЗначения(НомСтр,1));
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	//описание параметров",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	//ДобавитьШагВМассивТестов(ВсеТесты,Снипет,ИмяПроцедуры,ПредставлениеТеста,Транзакция,Параметр);",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"",ИнкрементЗначения(НомСтр,1));
	
	
	ФайлФичи = Новый Файл(ИмяФайлаФичи);
	ИмяEPFФичи = ФайлФичи.Путь + "step_definitions\" + ФайлФичи.ИмяБезРасширения + ".epf";
	
	
	//добавим строки, которые были раньше, но их нет в текущей фиче
	//это бывает, когда мы хотим добавить шаг,в библиотеку сначала из одной фичи, потом из другой
	Для каждого СтрКодПроцедурыПолучитьСписокТестов Из КодПроцедурыПолучитьСписокТестов Цикл
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,СтрКодПроцедурыПолучитьСписокТестов.Стр,ИнкрементЗначения(НомСтр,1));
	КонецЦикла;
	
	
	
	МассивДобавленыхСнипетов = Новый Массив;
	Для каждого Снипет Из Снипеты Цикл
		СнипетУжеБылВДругойEPF = ?(СокрЛП(Снипет.АдресСнипета) = "",Ложь,Истина);
		Если НРег(ИмяEPFФичи) = НРег(Снипет.АдресСнипета) Тогда
			СнипетУжеБылВДругойEPF = Ложь;
		КонецЕсли;	
		
		Если Не СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур Тогда
			Если СнипетУжеБылВДругойEPF Тогда
				Продолжить;
			КонецЕсли;  
		КонецЕсли;  
		
		ПрефиксКомментарий     = ?(СнипетУжеБылВДругойEPF,"//","");
		ПостфиксКомментарий    = ?(СнипетУжеБылВДругойEPF," //уже был в " + Снипет.АдресСнипета,"");
		
		
		Зн = МассивДобавленыхСнипетов.Найти(Снипет.StepDefinition);
		Если Зн <> Неопределено Тогда
			Продолжить;
		КонецЕсли;	 
		ИмяПроцедуры = Снипет.StepDefinition;
		Поз = Найти(ИмяПроцедуры,"(");
		ИмяПроцедуры = Лев(ИмяПроцедуры,Поз-1);
		
		ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ПрефиксКомментарий + "	ДобавитьШагВМассивТестов(ВсеТесты,""" + Снипет.StepDefinition + """,""" + ИмяПроцедуры + """,""" + СтрЗаменить(Снипет.Шаг,"""","""""") + """);" + ПостфиксКомментарий,ИнкрементЗначения(НомСтр,1));
		МассивДобавленыхСнипетов.Добавить(Снипет.StepDefinition);
	КонецЦикла;
	
	
	
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"",ИнкрементЗначения(НомСтр,1));
	ДобавитьСтрокуВМодуль(ТелоМодуля,ШагСтрокДляМодуля,"	Возврат ВсеТесты;",ИнкрементЗначения(НомСтр,1));
	
	
	ТелоМодуля.Сортировать("НомСтр");
	
	
	
	
	Если ЭтоУФ Тогда
		ТелоМодуля = ЗначениеВСтрокуВнутр(ТелоМодуля);
	КонецЕсли;	 
	
	
	
КонецПроцедуры

Процедура УдалитьИсходникиEPF(ИмяФайлаEpf)
	ФайлEpf = Новый Файл(ИмяФайлаEpf);
	Если Не ФайлEpf.Существует() Тогда
		ВызватьИсключение "Файл " + ИмяФайлаEpf + " не существует!";
	КонецЕсли;	 
	
	
	Путь = ФайлEpf.Путь + "Src";
	ФайлИсходники = Новый Файл(Путь);
	Если ФайлИсходники.Существует() Тогда
		УдалитьФайлы(Путь);
	КонецЕсли;	 
КонецПроцедуры

Процедура ВыполнитьКомандуОС(Стр)
	#Если Клиент Тогда
		КомандаСистемы(Стр);
	#КонецЕсли
	
	Возврат;

	
	СистемнаяИнформация = Новый СистемнаяИнформация;
	
	Если (СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86) или (СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64) Тогда
		Попытка
			ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
			
			//ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,"UTF-8",,Истина); 
			ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.UTF8,,Истина); 
			ЗТ.ЗаписатьСтроку(Стр); 
			ЗТ.Закрыть();
			
			WshShell = Новый COMОбъект("WScript.Shell");
			//Сообщить(Стр);
			WshShell.Run(ИмяВременногоBAT,7,-1);	
			УдалитьФайлы(ИмяВременногоBAT);
		Исключение
			#Если Клиент Тогда
			КомандаСистемы(Стр);
			#КонецЕсли
		КонецПопытки;
	Иначе
		ВызватьИсключение "Команда системы реализована только под Windows.";
	КонецЕсли;	 
	
КонецПроцедуры

Функция ВПеременнойPathЕстьUnpackV8_exe()
	ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
	Стр = "V8Unpack.exe > " + ИмяФайлаЛога;
	
	ВыполнитьКомандуОС(Стр);
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаЛога,"UTF-8");
	
	СтрокаВозврата = Неопределено;
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		
		//"V8Upack Version 2.00 Copyright (c) 2008 Denis Demidov 2008-03-30"
		Если Найти(НРег(Стр),"version") > 0 Тогда
			Текст.Закрыть();
			Возврат Истина;
		КонецЕсли;	 
		
	КонецЦикла;	
	
	Текст.Закрыть();
	
	
	Возврат Ложь;
КонецФункции

Процедура СделатьGenerateEpf(СтруктураПараметров)
	
	Если Не ВПеременнойPathЕстьUnpackV8_exe() Тогда
		Сообщить("В переменной PATH не указан путь к ""v8unpack.exe"". Невозможно сделать сбор epf из исходников.");
		Возврат;
	КонецЕсли;	 
	
	
	
	ГенерироватьУФ          = СтруктураПараметров.ГенерироватьУФ;
	ШагСтрокДляМодуля       = СтруктураПараметров.ШагСтрокДляМодуля;
	DebugLog                = СтруктураПараметров.DebugLog;
	КаталогФич              = СтруктураПараметров.КаталогФич;
	КонтекстVanessaBehavoir = СтруктураПараметров.КонтекстVanessaBehavoir;
	КаталогиБиблиотек       = СтруктураПараметров.КаталогиБиблиотек;
	
	СоздаватьОбластиПриГенерацииКода = СтруктураПараметров.СоздаватьОбластиПриГенерацииКода;
	
	СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур       = СтруктураПараметров.СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур;
	
	
	//ТаблицаКонтекстовОбработок = Новый ТаблицаЗначений;
	//ТаблицаКонтекстовОбработок.Колонки.Добавить("ИмяФайла");
	//ТаблицаКонтекстовОбработок.Колонки.Добавить("Обработка");
	
	ТаблицаКонтекстовОбработок = Новый Массив;
	
	ТаблицаИзвестныхStepDefinition = СтруктураПараметров.ТаблицаИзвестныхStepDefinition;
	ТаблицаВерсийEPF               = СтруктураПараметров.ТаблицаВерсийEPF;
	
	//ТаблицаИзвестныхStepDefinition = Новый ТаблицаЗначений;
	//ТаблицаИзвестныхStepDefinition.Колонки.Добавить("ИмяФайла");
	//ТаблицаИзвестныхStepDefinition.Колонки.Добавить("Id");
	//ТаблицаИзвестныхStepDefinition.Колонки.Добавить("СтрокаРеальнойПроцедуры");
	//ТаблицаИзвестныхStepDefinition.Колонки.Добавить("Параметры");
	
	ПолучитьУжеСуществующиеСнипетыИзОбработок(КаталогФич,ТаблицаКонтекстовОбработок,ТаблицаИзвестныхStepDefinition,ТаблицаВерсийEPF,КонтекстVanessaBehavoir);
	Для каждого Элем Из КаталогиБиблиотек Цикл
		ПолучитьУжеСуществующиеСнипетыИзОбработок(Элем.Значение,ТаблицаКонтекстовОбработок,ТаблицаИзвестныхStepDefinition,ТаблицаВерсийEPF,КонтекстVanessaBehavoir);
	КонецЦикла;
	
	
	МассивФич   = СтруктураПараметров.МассивФич;
	МассивШагов = СтруктураПараметров.МассивШагов;
	Ном = 0;
	Для каждого ИмяФайлаФичи Из МассивФич Цикл
		Ном = Ном+1;
		Шаги = МассивШагов.Получить(Ном-1);
		
		ФайлФичи       = Новый Файл(ИмяФайлаФичи);
		ИмяТекущейФичи = ФайлФичи.ИмяБезРасширения;
		СделатьСообщение("Работаю по фиче: " + ИмяФайлаФичи);
		
		МассивДляСозданияEpf = Новый Массив;
		//ОтносительныйКаталогФичи = СтрЗаменить(ФайлФичи.Путь,КаталогИнструментов,"");
		ОтносительныйКаталогФичи = ФайлФичи.Путь;
		Если Прав(ОтносительныйКаталогФичи,1) = "\" Тогда
			ОтносительныйКаталогФичи = Лев(ОтносительныйКаталогФичи,СтрДлина(ОтносительныйКаталогФичи)-1);
		КонецЕсли;	 
		
		Отладка("ОтносительныйКаталогФичи=" + ОтносительныйКаталогФичи);
		СтруктураОписанияEpf = СоздатьСтруктураОписанияEpf(ОтносительныйКаталогФичи,ФайлФичи.ИмяБезРасширения,Истина,СоздаватьОбластиПриГенерацииКода);
		
		
		Снипеты = СнипетыПолучитьСнипетыПоШагам(Шаги);
		ЗаполнитьПроцедуруПолучитьСписокТестов(СтруктураОписанияEpf.ТелоМодуля,Снипеты,,ИмяФайлаФичи,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
		Для каждого ЭлемСнипет Из Снипеты Цикл
			ДобавитьStepDefinitionВТекстМодуля(СтруктураОписанияEpf,ЭлемСнипет.StepDefinition,ЭлемСнипет.Шаг,ШагСтрокДляМодуля,ЭлемСнипет.АдресСнипета,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур,ГенерироватьУФ);
		КонецЦикла;
		
		БылиОшибки = Ложь;
		СоздатьФайлыОбработок(БылиОшибки,СтруктураОписанияEpf);
		
		
		Если СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
			УдалитьИсходникиEPF(СтруктураОписанияEpf.ИмяФайлаEpf);
		КонецЕсли;	 
	КонецЦикла;
	
	
	СделатьСообщение("Создание epf по фичам закончено.");
	
КонецПроцедуры

Функция СоздатьТаблицуКлючевыхСлов_ru()
	Тзн = Новый Массив;
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"функция","feature");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"функционал","feature");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"свойство","feature");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"предыстория","background");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"контекст","background");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"сценарий","scenario");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"структура сценария","scenario_outline");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"примеры","examples");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"допустим","given");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"дано","given");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"пусть","given");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"если","when");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"когда","when");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"тогда","then");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"то","then");

	
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"к тому же","and");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"также","and");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"и","and");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"но","but");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"а","but");
	
	Возврат Тзн;
КонецФункции

Функция СоздатьТаблицуКлючевыхСлов_uk()
	Тзн = Новый Массив;
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"функціонал","feature");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"передумова","background");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"сценарій","scenario");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"структура сценарію","scenario_outline");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"приклади","examples");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"припустимо","given");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"дано","given");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"припустимо, що","given");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"нехай","given");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"якщо","when");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"коли","when");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"то","then");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"тоді","then");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"і","and");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"а також","and");
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"та","and");
	
	ДобавитьКлючевоеСловоВТаблицу(Тзн,"але","but");
	
	Возврат Тзн;
КонецФункции

ЭтоУФ = Ложь;

СоответствиеТаблицПереводов = Новый Соответствие;
СоответствиеТаблицПереводов.Вставить("ru", СоздатьТаблицуКлючевыхСлов_ru());
СоответствиеТаблицПереводов.Вставить("uk", СоздатьТаблицуКлючевыхСлов_uk());



ТекущийЯзыкФичаФайла = "ru";
ПредставлениеВертЧертыВТабДок = "__&ВертЧерта__";